Merge remote-tracking branch 'origin/master' into BETA_JAVA_12

# Conflicts:
#	org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaCoreOptionsTests.java

Change-Id: I406b6d7693cc43faf7f2365f39514b2173b92ca3
diff --git a/CONTRIBUTING b/CONTRIBUTING
new file mode 100644
index 0000000..137f076
--- /dev/null
+++ b/CONTRIBUTING
@@ -0,0 +1,59 @@
+# Contributing to Eclipse Java development tools
+
+Thanks for your interest in this project.
+
+## Project description
+
+The JDT project provides the tool plug-ins that implement a Java IDE supporting
+the development of any Java application, including Eclipse plug-ins. It adds a
+Java project nature and Java perspective to the Eclipse Workbench as well as a
+number of views, editors, wizards, builders, and code merging and refactoring
+tools. The JDT project allows Eclipse to be a development environment for
+itself.
+
+* https://projects.eclipse.org/projects/eclipse.jdt
+
+## Developer resources
+
+Information regarding source code management, builds, coding standards, and
+more.
+
+* https://projects.eclipse.org/projects/eclipse.jdt/developer
+
+The project maintains the following source code repositories
+
+* http://git.eclipse.org/c/jdt/eclipse.jdt.core.binaries.git
+* http://git.eclipse.org/c/jdt/eclipse.jdt.core.git
+* http://git.eclipse.org/c/jdt/eclipse.jdt.debug.git
+* http://git.eclipse.org/c/jdt/eclipse.jdt.git
+* http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git
+
+This project uses Bugzilla to track ongoing development and issues.
+
+* Search for issues: https://eclipse.org/bugs/buglist.cgi?product=JDT
+* Create a new report: https://eclipse.org/bugs/enter_bug.cgi?product=JDT
+
+Be sure to search for existing bugs before you create another one. Remember that
+contributions are always welcome!
+
+## Eclipse Contributor Agreement
+
+Before your contribution can be accepted by the project team contributors must
+electronically sign the Eclipse Contributor Agreement (ECA).
+
+* http://www.eclipse.org/legal/ECA.php
+
+Commits that are provided by non-committers must have a Signed-off-by field in
+the footer indicating that the author is aware of the terms by which the
+contribution has been provided to the project. The non-committer must
+additionally have an Eclipse Foundation account and must have a signed Eclipse
+Contributor Agreement (ECA) on file.
+
+For more information, please see the Eclipse Committer Handbook:
+https://www.eclipse.org/projects/handbook/#resources-commit
+
+## Contact
+
+Contact the project developers via the project's "dev" list.
+
+* https://dev.eclipse.org/mailman/listinfo/jdt-dev
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..e23ece2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,277 @@
+Eclipse Public License - v 2.0
+
+    THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+    PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
+    OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+  a) in the case of the initial Contributor, the initial content
+     Distributed under this Agreement, and
+
+  b) in the case of each subsequent Contributor:
+     i) changes to the Program, and
+     ii) additions to the Program;
+  where such changes and/or additions to the Program originate from
+  and are Distributed by that particular Contributor. A Contribution
+  "originates" from a Contributor if it was added to the Program by
+  such Contributor itself or anyone acting on such Contributor's behalf.
+  Contributions do not include changes or additions to the Program that
+  are not Modified Works.
+
+"Contributor" means any person or entity that Distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which
+are necessarily infringed by the use or sale of its Contribution alone
+or when combined with the Program.
+
+"Program" means the Contributions Distributed in accordance with this
+Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement
+or any Secondary License (as applicable), including Contributors.
+
+"Derivative Works" shall mean any work, whether in Source Code or other
+form, that is based on (or derived from) the Program and for which the
+editorial revisions, annotations, elaborations, or other modifications
+represent, as a whole, an original work of authorship.
+
+"Modified Works" shall mean any work in Source Code or other form that
+results from an addition to, deletion from, or modification of the
+contents of the Program, including, for purposes of clarity any new file
+in Source Code form that contains any contents of the Program. Modified
+Works shall not include works that contain only declarations,
+interfaces, types, classes, structures, or files of the Program solely
+in each case in order to link to, bind by name, or subclass the Program
+or Modified Works thereof.
+
+"Distribute" means the acts of a) distributing or b) making available
+in any manner that enables the transfer of a copy.
+
+"Source Code" means the form of a Program preferred for making
+modifications, including but not limited to software source code,
+documentation source, and configuration files.
+
+"Secondary License" means either the GNU General Public License,
+Version 2.0, or any later versions of that license, including any
+exceptions or additional permissions as identified by the initial
+Contributor.
+
+2. GRANT OF RIGHTS
+
+  a) Subject to the terms of this Agreement, each Contributor hereby
+  grants Recipient a non-exclusive, worldwide, royalty-free copyright
+  license to reproduce, prepare Derivative Works of, publicly display,
+  publicly perform, Distribute and sublicense the Contribution of such
+  Contributor, if any, and such Derivative Works.
+
+  b) Subject to the terms of this Agreement, each Contributor hereby
+  grants Recipient a non-exclusive, worldwide, royalty-free patent
+  license under Licensed Patents to make, use, sell, offer to sell,
+  import and otherwise transfer the Contribution of such Contributor,
+  if any, in Source Code or other form. This patent license shall
+  apply to the combination of the Contribution and the Program if, at
+  the time the Contribution is added by the Contributor, such addition
+  of the Contribution causes such combination to be covered by the
+  Licensed Patents. The patent license shall not apply to any other
+  combinations which include the Contribution. No hardware per se is
+  licensed hereunder.
+
+  c) Recipient understands that although each Contributor grants the
+  licenses to its Contributions set forth herein, no assurances are
+  provided by any Contributor that the Program does not infringe the
+  patent or other intellectual property rights of any other entity.
+  Each Contributor disclaims any liability to Recipient for claims
+  brought by any other entity based on infringement of intellectual
+  property rights or otherwise. As a condition to exercising the
+  rights and licenses granted hereunder, each Recipient hereby
+  assumes sole responsibility to secure any other intellectual
+  property rights needed, if any. For example, if a third party
+  patent license is required to allow Recipient to Distribute the
+  Program, it is Recipient's responsibility to acquire that license
+  before distributing the Program.
+
+  d) Each Contributor represents that to its knowledge it has
+  sufficient copyright rights in its Contribution, if any, to grant
+  the copyright license set forth in this Agreement.
+
+  e) Notwithstanding the terms of any Secondary License, no
+  Contributor makes additional grants to any Recipient (other than
+  those set forth in this Agreement) as a result of such Recipient's
+  receipt of the Program under the terms of a Secondary License
+  (if permitted under the terms of Section 3).
+
+3. REQUIREMENTS
+
+3.1 If a Contributor Distributes the Program in any form, then:
+
+  a) the Program must also be made available as Source Code, in
+  accordance with section 3.2, and the Contributor must accompany
+  the Program with a statement that the Source Code for the Program
+  is available under this Agreement, and informs Recipients how to
+  obtain it in a reasonable manner on or through a medium customarily
+  used for software exchange; and
+
+  b) the Contributor may Distribute the Program under a license
+  different than this Agreement, provided that such license:
+     i) effectively disclaims on behalf of all other Contributors all
+     warranties and conditions, express and implied, including
+     warranties or conditions of title and non-infringement, and
+     implied warranties or conditions of merchantability and fitness
+     for a particular purpose;
+
+     ii) effectively excludes on behalf of all other Contributors all
+     liability for damages, including direct, indirect, special,
+     incidental and consequential damages, such as lost profits;
+
+     iii) does not attempt to limit or alter the recipients' rights
+     in the Source Code under section 3.2; and
+
+     iv) requires any subsequent distribution of the Program by any
+     party to be under a license that satisfies the requirements
+     of this section 3.
+
+3.2 When the Program is Distributed as Source Code:
+
+  a) it must be made available under this Agreement, or if the
+  Program (i) is combined with other material in a separate file or
+  files made available under a Secondary License, and (ii) the initial
+  Contributor attached to the Source Code the notice described in
+  Exhibit A of this Agreement, then the Program may be made available
+  under the terms of such Secondary Licenses, and
+
+  b) a copy of this Agreement must be included with each copy of
+  the Program.
+
+3.3 Contributors may not remove or alter any copyright, patent,
+trademark, attribution notices, disclaimers of warranty, or limitations
+of liability ("notices") contained within the Program from any copy of
+the Program which they Distribute, provided that Contributors may add
+their own appropriate notices.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities
+with respect to end users, business partners and the like. While this
+license is intended to facilitate the commercial use of the Program,
+the Contributor who includes the Program in a commercial product
+offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes
+the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and indemnify every
+other Contributor ("Indemnified Contributor") against any losses,
+damages and costs (collectively "Losses") arising from claims, lawsuits
+and other legal actions brought by a third party against the Indemnified
+Contributor to the extent caused by the acts or omissions of such
+Commercial Contributor in connection with its distribution of the Program
+in a commercial product offering. The obligations in this section do not
+apply to any claims or Losses relating to any actual or alleged
+intellectual property infringement. In order to qualify, an Indemnified
+Contributor must: a) promptly notify the Commercial Contributor in
+writing of such claim, and b) allow the Commercial Contributor to control,
+and cooperate with the Commercial Contributor in, the defense and any
+related settlement negotiations. The Indemnified Contributor may
+participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those performance
+claims and warranties, and if a court requires any other Contributor to
+pay any damages as a result, the Commercial Contributor must pay
+those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
+BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
+TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+PURPOSE. Each Recipient is solely responsible for determining the
+appropriateness of using and distributing the Program and assumes all
+risks associated with its exercise of rights under this Agreement,
+including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs
+or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
+SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other software
+or hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement,
+but in order to avoid inconsistency the Agreement is copyrighted and
+may only be modified in the following manner. The Agreement Steward
+reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement
+Steward has the right to modify this Agreement. The Eclipse Foundation
+is the initial Agreement Steward. The Eclipse Foundation may assign the
+responsibility to serve as the Agreement Steward to a suitable separate
+entity. Each new version of the Agreement will be given a distinguishing
+version number. The Program (including Contributions) may always be
+Distributed subject to the version of the Agreement under which it was
+received. In addition, after a new version of the Agreement is published,
+Contributor may elect to Distribute the Program (including its
+Contributions) under the new version.
+
+Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
+receives no rights or licenses to the intellectual property of any
+Contributor under this Agreement, whether expressly, by implication,
+estoppel or otherwise. All rights in the Program not expressly granted
+under this Agreement are reserved. Nothing in this Agreement is intended
+to be enforceable by any entity that is not a Contributor or Recipient.
+No third-party beneficiary rights are created under this Agreement.
+
+Exhibit A - Form of Secondary Licenses Notice
+
+"This Source Code may also be made available under the following 
+Secondary Licenses when the conditions for such availability set forth 
+in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
+version(s), and exceptions or additional permissions here}."
+
+  Simply including a copy of this Agreement, including this Exhibit A
+  is not sufficient to license the Source Code under Secondary Licenses.
+
+  If it is not possible or desirable to put the notice in a particular
+  file, then You may include the notice in a location (such as a LICENSE
+  file in a relevant directory) where a recipient would be likely to
+  look for such a notice.
+
+  You may add additional accurate notices of copyright ownership.
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..62de25b
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,35 @@
+# Notices for Eclipse Java development tools
+
+This content is produced and maintained by the Eclipse Java development tools
+project.
+
+* Project home: https://projects.eclipse.org/projects/eclipse.jdt
+
+## Trademarks
+
+Eclipse Java development tools, Java development tools, Eclipse JDT, and JDT are
+trademarks of the Eclipse Foundation.
+
+## Copyright
+
+All content is the property of the respective authors or their employers. For
+more information regarding authorship of content, please consult the listed
+source code repository logs.
+
+## Declared Project Licenses
+
+This program and the accompanying materials are made available under the terms
+of the Eclipse Public License v. 2.0 which is available at
+http://www.eclipse.org/legal/epl-2.0.
+
+SPDX-License-Identifier: EPL-2.0
+
+## Source Code
+
+The project maintains the following source code repositories:
+
+* http://git.eclipse.org/c/jdt/eclipse.jdt.core.binaries.git
+* http://git.eclipse.org/c/jdt/eclipse.jdt.core.git
+* http://git.eclipse.org/c/jdt/eclipse.jdt.debug.git
+* http://git.eclipse.org/c/jdt/eclipse.jdt.git
+* http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git
\ No newline at end of file
diff --git a/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolJava9Tests.java b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolJava9Tests.java
index dcb6b28..83133f1 100644
--- a/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolJava9Tests.java
+++ b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolJava9Tests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2017 IBM Corporation and others.
+ * Copyright (c) 2017, 2018 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -725,10 +725,6 @@
 			super.report(diagnostic);
 		}
 		
-		public int getErrorCount() {
-			return errorList.size();
-		}
-		
 		public boolean hasDiagnostic(String match) {
 			for(Diagnostic<? extends JavaFileObject> d: errorList) {
 				String msg = d.getMessage(Locale.US).toLowerCase();
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java
index d1f50ca..15771d9 100644
--- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java
@@ -94,7 +94,7 @@
 				performCompilation();
 			}
 		} catch(IllegalArgumentException e) {
-			diagnosticListener.report(new ExceptionDiagnostic(e));
+			this.diagnosticListener.report(new ExceptionDiagnostic(e));
 			this.logger.logException(e);
 			if (this.systemExitWhenFinished) {
 				cleanup();
@@ -102,7 +102,7 @@
 			}
 			return false;
 		} catch (RuntimeException e) { // internal compiler failure
-			diagnosticListener.report(new ExceptionDiagnostic(e));
+			this.diagnosticListener.report(new ExceptionDiagnostic(e));
 			e.printStackTrace();
 			this.logger.logException(e);
 			return false;
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/ExceptionDiagnostic.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/ExceptionDiagnostic.java
index 8822b36..5afe834 100644
--- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/ExceptionDiagnostic.java
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/ExceptionDiagnostic.java
@@ -17,7 +17,6 @@
 
 import javax.tools.Diagnostic;
 import javax.tools.JavaFileObject;
-import javax.tools.Diagnostic.Kind;
 
 final class ExceptionDiagnostic implements Diagnostic<JavaFileObject> {
 	private final Exception exception;
@@ -28,7 +27,7 @@
 
 	@Override
 	public String getCode() {
-		return "exception";
+		return "exception"; //$NON-NLS-1$
 	}
 
 	@Override
@@ -53,7 +52,7 @@
 
 	@Override
 	public String getMessage(Locale arg0) {
-		return exception.toString();
+		return this.exception.toString();
 	}
 
 	@Override
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
index 426340e..6bba0e9 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
@@ -248,6 +248,10 @@
 		StringBuffer classpathBuffer = new StringBuffer(" -classpath ");
 		this.classpath = classpathBuffer.toString();
 	}
+	/** Call this if " -classpath " should be replaced by some other option token. */
+	protected void usePathOption(String option) {
+		this.classpath = option;
+	}
 	static String getVersion(String javacPathName) throws IOException, InterruptedException {
 		Process fetchVersionProcess = null;
 		try {
@@ -1028,7 +1032,7 @@
 	// list of available javac compilers, as defined by the jdk.roots
 	// variable, which should hold a File.pathSeparatorChar separated
 	// list of paths for to-be-tested JDK root directories
-	protected static List javacCompilers = null;
+	protected static List<JavacCompiler> javacCompilers = null;
 
 	public static final String OUTPUT_DIR = Util.getOutputDirectory() + File.separator + "regression";
 	public static final String LIB_DIR = Util.getOutputDirectory() + File.separator + "lib";
@@ -1881,7 +1885,15 @@
 				expectedSuccessOutputString,
 				null,
 				javacTestOptions);
+	}
+
+	protected static void javacUsePathOption(String option) {
+		if (AbstractRegressionTest.javacCompilers != null) {
+			for (JavacCompiler compiler : AbstractRegressionTest.javacCompilers) {
+				compiler.usePathOption(option);
+			}
 		}
+	}
 
 	/*
 	 * Run Sun compilation using javac.
@@ -2196,9 +2208,9 @@
 		}
 	}
 	String testName = testName();
-	Iterator compilers = javacCompilers.iterator();
+	Iterator<JavacCompiler> compilers = javacCompilers.iterator();
 	while (compilers.hasNext()) {
-		JavacCompiler compiler = (JavacCompiler) compilers.next();
+		JavacCompiler compiler = compilers.next();
 		if (!options.skip(compiler) && compiler.compliance == this.complianceLevel) {
 			// WORK this may exclude some compilers under some conditions (when
 			//      complianceLevel is not set); consider accepting the compiler
@@ -2220,6 +2232,7 @@
 				for (int i = 0, length = testFiles.length; i < length; ) {
 					String fileName = testFiles[i++];
 					String contents = testFiles[i++];
+					fileName = expandFileNameForJavac(fileName);
 					File file = new File(javacOutputDirectory, fileName);
 					if (fileName.lastIndexOf('/') >= 0) {
 						File dir = file.getParentFile();
@@ -2233,7 +2246,7 @@
 				int testFilesLength = testFiles.length;
 				sourceFileNames = new String[testFilesLength / 2];
 				for (int i = 0, j = 0; i < testFilesLength; i += 2, j++) {
-					sourceFileNames[j] = testFiles[i];
+					sourceFileNames[j] = expandFileNameForJavac(testFiles[i]);
 				}
 
 				// compile
@@ -2336,6 +2349,10 @@
 		}
 	}
 }
+/** Hook for AbstractRegressionTest9 */
+protected String expandFileNameForJavac(String fileName) {
+	return fileName;
+}
 void handleMismatch(JavacCompiler compiler, String testName, String[] testFiles, String expectedCompilerLog,
 		String expectedOutputString, String expectedErrorString, StringBuffer compilerLog, String output, String err,
 		JavacTestOptions.Excuse excuse, int mismatch) {
@@ -3585,7 +3602,7 @@
 					System.out.println("* Sun Javac compiler output archived into file:");
 					System.out.println("* " + javacFullLogFileName);
 					System.out.println("***************************************************************************");
-					javacCompilers = new ArrayList();
+					javacCompilers = new ArrayList<>();
 					String jdkRoots = System.getProperty("jdk.roots");
 					if (jdkRoots == null) {
 						javacCompilers.add(new JavacCompiler(jdkRootDirPath.toString()));
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest9.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest9.java
index cc49625..57db3e4 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest9.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest9.java
@@ -89,6 +89,18 @@
 		return compilationUnits;
 	}
 
+	/**
+	 * javac cannot leverage our internal map  {@code file2module}, so we better
+	 * neatly place each file into a sub directory matching the module name.
+	 */
+	protected String expandFileNameForJavac(String fileName) {
+		String fileNameAsKey = fileName.replace(File.separator, "/");
+		if (this.file2module != null && this.file2module.containsKey(fileNameAsKey)) {
+			fileName = new String(this.file2module.get(fileNameAsKey))+File.separator+fileName;
+		}
+		return fileName;
+	}
+
 	private IModule extractModuleDesc(String fileName, String fileContent, ICompilationUnit cu) {
 		if (fileName.toLowerCase().endsWith(IModule.MODULE_INFO_JAVA)) {
 			Parser parser = createParser();
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Deprecated9Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Deprecated9Test.java
index f5828ae..6f12b7d 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Deprecated9Test.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Deprecated9Test.java
@@ -688,7 +688,8 @@
 		runner.runNegativeTest();
 	}
 	public void testDeprecatedProvidedServices() {
-		associateToModule("mod0", "p1/IServiceDep.java", "p1/IServiceDepSince.java", "p1/IServiceTermDep.java", "p1/IServiceTermDepSince.java");
+		javacUsePathOption(" --module-source-path ");
+		associateToModule("mod0", "module-info.java", "p1/IServiceDep.java", "p1/IServiceDepSince.java", "p1/IServiceTermDep.java", "p1/IServiceTermDepSince.java");
 		associateToModule("mod1", "p1impl/ServiceDep.java", "p1impl/ServiceDepSince.java", "p1impl/ServiceTermDep.java", "p1impl/ServiceTermDepSince.java");
 		Runner runner = new Runner();
 		runner.customOptions = new HashMap<>();
@@ -732,7 +733,7 @@
 				"package p1impl;\n" +
 				"@Deprecated(since=\"3\",forRemoval=true)\n" +
 				"public class ServiceTermDepSince implements p1.IServiceTermDepSince {}\n",
-				"folder2/module-info.java",
+				"mod1/module-info.java",
 				"module mod1 {\n" +
 				"	requires mod0;\n" +
 				"	provides p1.IServiceDep with p1impl.ServiceDep;\n" +
@@ -743,42 +744,42 @@
 			};
 		runner.expectedCompilerLog =
 			"----------\n" + 
-			"1. INFO in folder2\\module-info.java (at line 3)\n" + 
+			"1. INFO in mod1\\module-info.java (at line 3)\n" + 
 			"	provides p1.IServiceDep with p1impl.ServiceDep;\n" + 
 			"	            ^^^^^^^^^^^\n" + 
 			"The type IServiceDep is deprecated\n" + 
 			"----------\n" + 
-			"2. INFO in folder2\\module-info.java (at line 3)\n" + 
+			"2. INFO in mod1\\module-info.java (at line 3)\n" + 
 			"	provides p1.IServiceDep with p1impl.ServiceDep;\n" + 
 			"	                                    ^^^^^^^^^^\n" + 
 			"The type ServiceDep is deprecated\n" + 
 			"----------\n" + 
-			"3. INFO in folder2\\module-info.java (at line 4)\n" + 
+			"3. INFO in mod1\\module-info.java (at line 4)\n" + 
 			"	provides p1.IServiceDepSince with p1impl.ServiceDepSince;\n" + 
 			"	            ^^^^^^^^^^^^^^^^\n" + 
 			"The type IServiceDepSince is deprecated since version 2\n" + 
 			"----------\n" + 
-			"4. INFO in folder2\\module-info.java (at line 4)\n" + 
+			"4. INFO in mod1\\module-info.java (at line 4)\n" + 
 			"	provides p1.IServiceDepSince with p1impl.ServiceDepSince;\n" + 
 			"	                                         ^^^^^^^^^^^^^^^\n" + 
 			"The type ServiceDepSince is deprecated since version 2\n" + 
 			"----------\n" + 
-			"5. WARNING in folder2\\module-info.java (at line 5)\n" + 
+			"5. WARNING in mod1\\module-info.java (at line 5)\n" + 
 			"	provides p1.IServiceTermDep with p1impl.ServiceTermDep;\n" + 
 			"	            ^^^^^^^^^^^^^^^\n" + 
 			"The type IServiceTermDep has been deprecated and marked for removal\n" + 
 			"----------\n" + 
-			"6. WARNING in folder2\\module-info.java (at line 5)\n" + 
+			"6. WARNING in mod1\\module-info.java (at line 5)\n" + 
 			"	provides p1.IServiceTermDep with p1impl.ServiceTermDep;\n" + 
 			"	                                        ^^^^^^^^^^^^^^\n" + 
 			"The type ServiceTermDep has been deprecated and marked for removal\n" + 
 			"----------\n" + 
-			"7. WARNING in folder2\\module-info.java (at line 6)\n" + 
+			"7. WARNING in mod1\\module-info.java (at line 6)\n" + 
 			"	provides p1.IServiceTermDepSince with p1impl.ServiceTermDepSince;\n" + 
 			"	            ^^^^^^^^^^^^^^^^^^^^\n" + 
 			"The type IServiceTermDepSince has been deprecated since version 3 and marked for removal\n" + 
 			"----------\n" + 
-			"8. WARNING in folder2\\module-info.java (at line 6)\n" + 
+			"8. WARNING in mod1\\module-info.java (at line 6)\n" + 
 			"	provides p1.IServiceTermDepSince with p1impl.ServiceTermDepSince;\n" + 
 			"	                                             ^^^^^^^^^^^^^^^^^^^\n" + 
 			"The type ServiceTermDepSince has been deprecated since version 3 and marked for removal\n" + 
@@ -786,6 +787,8 @@
 		runner.runWarningTest();
 	}
 	public void testDeprecatedUsedServices() {
+		javacUsePathOption(" --module-path ");
+
 		associateToModule("mod0", "p1/IServiceDep.java", "p1/IServiceDepSince.java", "p1/IServiceTermDep.java", "p1/IServiceTermDepSince.java");
 		Runner runner = new Runner();
 		runner.customOptions = new HashMap<>();
@@ -864,18 +867,54 @@
 				"	requires jdk.xml.bind;\n" +
 				"}\n"
 			};
-			runner.expectedCompilerLog =
-				"----------\n" + 
-				"1. WARNING in module-info.java (at line 2)\n" + 
-				"	requires jdk.xml.bind;\n" + 
-				"	         ^^^^^^^^^^^^\n" + 
-				"The module jdk.xml.bind has been deprecated since version 9 and marked for removal\n" + 
-				"----------\n";
-			runner.runWarningTest();
+			if (isJRE11Plus) {
+				runner.expectedCompilerLog =
+					"----------\n" + 
+					"1. ERROR in module-info.java (at line 2)\n" + 
+					"	requires jdk.xml.bind;\n" + 
+					"	         ^^^^^^^^^^^^\n" + 
+					"jdk.xml.bind cannot be resolved to a module\n" + 
+					"----------\n";
+				runner.runNegativeTest();
+			} else {
+				runner.expectedCompilerLog =
+					"----------\n" + 
+					"1. WARNING in module-info.java (at line 2)\n" + 
+					"	requires jdk.xml.bind;\n" + 
+					"	         ^^^^^^^^^^^^\n" + 
+					"The module jdk.xml.bind has been deprecated since version 9 and marked for removal\n" + 
+					"----------\n";
+				runner.runWarningTest();
+			}
 		} finally {
 			this.javaClassLib = save;
 		}
 	}
+	public void testBug533063_2() throws Exception {
+		javacUsePathOption(" --module-path ");
+
+		runConformTest(new String[] {
+			"dont.use/module-info.java",
+			"@Deprecated(forRemoval=true,since=\"9\") module dont.use {}\n"
+		});
+		this.moduleMap.clear(); // don't use the source module beyond this point
+		Runner runner = new Runner();
+		runner.shouldFlushOutputDirectory = false;
+		runner.testFiles = new String[] {
+			"my.mod/module-info.java",
+			"module my.mod {\n" +
+			"	requires dont.use;\n" +
+			"}\n"
+		};
+		runner.expectedCompilerLog =
+			"----------\n" + 
+			"1. WARNING in my.mod\\module-info.java (at line 2)\n" + 
+			"	requires dont.use;\n" + 
+			"	         ^^^^^^^^\n" + 
+			"The module dont.use has been deprecated since version 9 and marked for removal\n" + 
+			"----------\n";
+		runner.runWarningTest();
+	}
 	public void testBug534304() throws Exception {
 		runNegativeTest(
 			new String[] {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LocalVariableTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LocalVariableTest.java
index cf2ad8a..5f7992e 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LocalVariableTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LocalVariableTest.java
@@ -897,6 +897,8 @@
 			"    }\n" + 
 			"}\n"
 		},
+		this.complianceLevel < ClassFileConstants.JDK11
+		?
 		"----------\n" + 
 		"1. WARNING in ShowBug.java (at line 9)\n" + 
 		"	final X x = new X() {\n" + 
@@ -907,6 +909,13 @@
 		"	x.x(val - 1);\n" + 
 		"	^\n" + 
 		"The local variable x may not have been initialized\n" + 
+		"----------\n"
+		:
+		"----------\n" + 
+		"1. ERROR in ShowBug.java (at line 13)\n" + 
+		"	x.x(val - 1);\n" + 
+		"	^\n" + 
+		"The local variable x may not have been initialized\n" + 
 		"----------\n");
 }
 public static Class testClass() {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
index e674649..74b75a5 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
@@ -40,7 +40,7 @@
 public class ModuleCompilationTests extends AbstractBatchCompilerTest {
 
 	static {
-//		 TESTS_NAMES = new String[] { "test_npe_bug535107" };
+//		 TESTS_NAMES = new String[] { "testBug540067e" };
 		// TESTS_NUMBERS = new int[] { 1 };
 		// TESTS_RANGE = new int[] { 298, -1 };
 	}
@@ -162,8 +162,7 @@
 			if (javacCommandLine == null) {
 				javacCommandLine = adjustForJavac(commandLine, null);
 			}
-			for (Object comp : javacCompilers) {
-				JavacCompiler javacCompiler = (JavacCompiler) comp;
+			for (JavacCompiler javacCompiler : javacCompilers) {
 				if (javacCompiler.compliance < ClassFileConstants.JDK9)
 					continue;
 				if (options.skip(javacCompiler)) {
@@ -240,8 +239,7 @@
 			File outputDir = new File(OUTPUT_DIR);
 			final Set<String> outFiles = new HashSet<>();
 			walkOutFiles(output, outFiles, true);
-			for (Object comp : javacCompilers) {
-				JavacCompiler javacCompiler = (JavacCompiler) comp;
+			for (JavacCompiler javacCompiler : javacCompilers) {
 				if (javacCompiler.compliance < ClassFileConstants.JDK9)
 					continue;
 				JavacTestOptions.Excuse excuse = options.excuseFor(javacCompiler);
@@ -3632,11 +3630,7 @@
 			"	        ^^\n" + 
 			"The package p1 does not exist or is empty\n" + 
 			"----------\n" +
-			"----------\n" + 
-			"2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/p1/X.java\n" + 
-			"Must declare a named package because this compilation unit is associated to the named module \'mod.one\'\n" + 
-			"----------\n" + 
-			"2 problems (2 errors)\n",
+			"1 problem (1 error)\n",
 			false,
 			"empty",
 			OUTPUT_DIR + File.separator + out);
@@ -5006,4 +5000,200 @@
 		        "",
 		        true);
 	}
+	public void testBug540067a() {
+		File outputDirectory = new File(OUTPUT_DIR);
+		Util.flushDirectoryContent(outputDirectory);
+		String out = "bin";
+		String directory = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = directory + File.separator + "mod.one";
+		List<String> files = new ArrayList<>(); 
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						" exports p;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "X.java", 
+				"package p;\n" +
+				"public class X {\n" +
+				"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p" + File.separator + "q", "Test.java", 
+				"/*nothing in it */");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" --module-source-path " + "\"" + directory + "\" ")
+			.append(moduleLoc + File.separator + "module-info.java ")
+			.append(moduleLoc + File.separator + "p" + File.separator + "X.java ")
+			.append(moduleLoc + File.separator + "p" + File.separator + "q" + File.separator + "Test.java");
+
+		runConformModuleTest(
+				new String[0],
+				buffer.toString(),
+				"",
+				"",
+				false);
+	}
+	public void testBug540067b() {
+		File outputDirectory = new File(OUTPUT_DIR);
+		Util.flushDirectoryContent(outputDirectory);
+		String out = "bin";
+		String directory = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = directory + File.separator + "mod.one";
+		List<String> files = new ArrayList<>(); 
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						" exports p;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "X.java", 
+				"package p;\n" +
+				"public class X {\n" +
+				"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p" + File.separator + "q", "Test.java", 
+				"package p.q;");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" --module-source-path " + "\"" + directory + "\" ")
+			.append(moduleLoc + File.separator + "module-info.java ")
+			.append(moduleLoc + File.separator + "p" + File.separator + "X.java ")
+			.append(moduleLoc + File.separator + "p" + File.separator + "q" + File.separator + "Test.java");
+
+		runConformModuleTest(
+				new String[0],
+				buffer.toString(),
+				"",
+				"",
+				false);
+	}
+	public void testBug540067c() {
+		File outputDirectory = new File(OUTPUT_DIR);
+		Util.flushDirectoryContent(outputDirectory);
+		String out = "bin";
+		String directory = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = directory + File.separator + "mod.one";
+		List<String> files = new ArrayList<>(); 
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						" exports p;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "X.java", 
+				"package p;\n" +
+				"public class X {\n" +
+				"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p" + File.separator + "q", "Test.java", 
+				"package p.q;\n"
+				+ "class Test {}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" --module-source-path " + "\"" + directory + "\" ")
+			.append(moduleLoc + File.separator + "module-info.java ")
+			.append(moduleLoc + File.separator + "p" + File.separator + "X.java ")
+			.append(moduleLoc + File.separator + "p" + File.separator + "q" + File.separator + "Test.java");
+
+		runConformModuleTest(
+				new String[0],
+				buffer.toString(),
+				"",
+				"",
+				false);
+	}
+	public void testBug540067d() {
+		File outputDirectory = new File(OUTPUT_DIR);
+		Util.flushDirectoryContent(outputDirectory);
+		String out = "bin";
+		String directory = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = directory + File.separator + "mod.one";
+		List<String> files = new ArrayList<>(); 
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						" exports p;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "X.java", 
+				"package p;\n" +
+				"public class X {\n" +
+				"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p" + File.separator + "q", "Test.java", 
+				"class Test {}");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" --module-source-path " + "\"" + directory + "\" ")
+			.append(moduleLoc + File.separator + "module-info.java ")
+			.append(moduleLoc + File.separator + "p" + File.separator + "X.java ")
+			.append(moduleLoc + File.separator + "p" + File.separator + "q" + File.separator + "Test.java");
+
+		runNegativeModuleTest(
+				new String[0],
+				buffer.toString(),
+				"",
+				"----------\n" + 
+				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/p/q/Test.java (at line 1)\n" + 
+				"	class Test {}\n" + 
+				"	^\n" + 
+				"Must declare a named package because this compilation unit is associated to the named module \'mod.one\'\n" + 
+				"----------\n" + 
+				"1 problem (1 error)\n",
+				false,
+				"unnamed package is not allowed in named modules");
+	}
+	public void testBug540067e() {
+		File outputDirectory = new File(OUTPUT_DIR);
+		Util.flushDirectoryContent(outputDirectory);
+		String out = "bin";
+		String directory = OUTPUT_DIR + File.separator + "src";
+		String moduleLoc = directory + File.separator + "mod.one";
+		List<String> files = new ArrayList<>(); 
+		writeFileCollecting(files, moduleLoc, "module-info.java", 
+						"module mod.one { \n" +
+						" exports p;\n" +
+						"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p", "X.java", 
+				"package p;\n" +
+				"public class X {\n" +
+				"}");
+		writeFileCollecting(files, moduleLoc + File.separator + "p" + File.separator + "q", "Test.java", 
+				"import java.lang.*;");
+
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+			.append(" -9 ")
+			.append(" -classpath \"")
+			.append(Util.getJavaClassLibsAsString())
+			.append("\" ")
+			.append(" -warn:-unused")
+			.append(" --module-source-path " + "\"" + directory + "\" ")
+			.append(moduleLoc + File.separator + "module-info.java ")
+			.append(moduleLoc + File.separator + "p" + File.separator + "X.java ")
+			.append(moduleLoc + File.separator + "p" + File.separator + "q" + File.separator + "Test.java");
+
+		runNegativeModuleTest(
+				new String[0],
+				buffer.toString(),
+				"",
+				"----------\n" + 
+				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/p/q/Test.java (at line 1)\n" + 
+				"	import java.lang.*;\n" + 
+				"	^\n" + 
+				"Must declare a named package because this compilation unit is associated to the named module \'mod.one\'\n" + 
+				"----------\n" + 
+				"1 problem (1 error)\n",
+				false,
+				"unnamed package is not allowed in named modules");
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
index 59f8347..0d2d7a5 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
@@ -5355,4 +5355,145 @@
 		"----------\n",
 		options);
 }
+public void testBug473317() {
+	if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // using diamond
+	Map<String, String> compilerOptions = getCompilerOptions();
+	compilerOptions.put(JavaCore.COMPILER_PB_SYNTHETIC_ACCESS_EMULATION, JavaCore.IGNORE);
+	runLeakTest(
+		new String[] {
+			"AutoCloseableEnhancedForTest.java",
+			"import java.util.Iterator;\n" + 
+			"\n" + 
+			"public class AutoCloseableEnhancedForTest\n" + 
+			"{\n" + 
+			"   private static class MyIterator<T> implements Iterator<T>\n" + 
+			"   {\n" + 
+			"      private T value;\n" + 
+			"      \n" + 
+			"      public MyIterator(T value)\n" + 
+			"      {\n" + 
+			"         this.value = value;\n" + 
+			"      }\n" + 
+			"      \n" + 
+			"      @Override\n" + 
+			"      public boolean hasNext()\n" + 
+			"      {\n" + 
+			"         return false;\n" + 
+			"      }\n" + 
+			"\n" + 
+			"      @Override\n" + 
+			"      public T next()\n" + 
+			"      {\n" + 
+			"         return value;\n" + 
+			"      }\n" + 
+			"   }\n" + 
+			"   \n" + 
+			"   private static class MyIterable<T> implements Iterable<T>, AutoCloseable\n" + 
+			"   {\n" + 
+			"      @Override\n" + 
+			"      public Iterator<T> iterator()\n" + 
+			"      {\n" + 
+			"         return new MyIterator<>(null);\n" + 
+			"      }\n" + 
+			"      \n" + 
+			"      @Override\n" + 
+			"      public void close() throws Exception\n" + 
+			"      {\n" + 
+			"      }\n" + 
+			"   }\n" + 
+			"   \n" + 
+			"   public static void main(String[] args)\n" + 
+			"   {\n" + 
+			"      // Not flagged as \"never closed.\"\n" + 
+			"      for (Object value : new MyIterable<>())\n" + 
+			"      {\n" + 
+			"         System.out.println(String.valueOf(value));\n" + 
+			"         \n" + 
+			"         break;\n" + 
+			"      }\n" + 
+			"      \n" + 
+			"      // Flagged as \"never closed.\"\n" + 
+			"      MyIterable<Object> iterable = new MyIterable<>();\n" + 
+			"      \n" + 
+			"      for (Object value : iterable)\n" + 
+			"      {\n" + 
+			"         System.out.println(String.valueOf(value));\n" + 
+			"         \n" + 
+			"         break;\n" + 
+			"      }\n" + 
+			"   }\n" + 
+			"}\n"
+		},
+		"----------\n" + 
+		"1. WARNING in AutoCloseableEnhancedForTest.java (at line 44)\n" + 
+		"	for (Object value : new MyIterable<>())\n" + 
+		"	                    ^^^^^^^^^^^^^^^^^^\n" + 
+		"Resource leak: \'<unassigned Closeable value>\' is never closed\n" + 
+		"----------\n" + 
+		"2. WARNING in AutoCloseableEnhancedForTest.java (at line 52)\n" + 
+		"	MyIterable<Object> iterable = new MyIterable<>();\n" + 
+		"	                   ^^^^^^^^\n" + 
+		"Resource leak: \'iterable\' is never closed\n" + 
+		"----------\n",
+		compilerOptions);
+}
+public void testBug541705() {
+	if (this.complianceLevel < ClassFileConstants.JDK1_7) return; // uses diamond
+	Runner runner = new Runner();
+	runner.customOptions = getCompilerOptions();
+	runner.customOptions.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
+	runner.testFiles = new String[] {
+		"Test.java",
+		"import java.util.*;\n" +
+		"import java.util.zip.*;\n" +
+		"import java.io.*;\n" +
+		"public class Test {\n" +
+		"	private static HashMap<String, ZipFile> fgZipFileCache = new HashMap<>(5);\n" + 
+		"	public static void closeArchives() {\n" + 
+		"		synchronized (fgZipFileCache) {\n" + 
+		"			for (ZipFile file : fgZipFileCache.values()) {\n" +
+		"				synchronized (file) {\n" + 
+		"					try {\n" + 
+		"						file.close();\n" + 
+		"					} catch (IOException e) {\n" + 
+		"						System.out.println(e);\n" + 
+		"					}\n" + 
+		"				}\n" + 
+		"			}\n" + 
+		"			fgZipFileCache.clear();\n" + 
+		"		}\n" + 
+		"	}\n" +
+		"}\n"
+	};
+	runner.runConformTest();
+}
+public void testBug541705b() {
+	if (this.complianceLevel < ClassFileConstants.JDK9) return; // variable used in t-w-r
+	Runner runner = new Runner();
+	runner.customOptions = getCompilerOptions();
+	runner.customOptions.put(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, CompilerOptions.ERROR);
+	runner.testFiles = new String[] {
+		"Test.java",
+		"import java.util.*;\n" +
+		"import java.util.zip.*;\n" +
+		"import java.io.*;\n" +
+		"public class Test {\n" +
+		"	private static HashMap<String, ZipFile> fgZipFileCache = new HashMap<>(5);\n" + 
+		"	public static void closeArchives() {\n" + 
+		"		synchronized (fgZipFileCache) {\n" + 
+		"			for (ZipFile file : fgZipFileCache.values()) {\n" + 
+		"				synchronized (file) {\n" + 
+		"					try (file) {\n" + 
+		"					} catch (IOException e) {\n" + 
+		"						System.out.println(e);\n" + 
+		"					}\n" + 
+		"				}\n" + 
+		"			}\n" + 
+		"			fgZipFileCache.clear();\n" + 
+		"		}\n" + 
+		"	}\n" +
+		"}\n"
+	};
+	runner.runConformTest();
+}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
index 283ad4e..7991fa0 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
@@ -405,6 +405,10 @@
 			if (version.startsWith("1.8.0_")) {
 				int build = Integer.parseInt(version.substring("1.8.0_".length()));
 				reflectNestedClassUseDollar = build >= 171; 
+			} else if (version.startsWith("1.8.0-")) {
+				// Some versions start with 1.8.0- but don't have build qualifier.
+				// Just assume they are > 171 build. Nothing much can be done.
+				reflectNestedClassUseDollar = true;
 			} else {
 				throw new IllegalStateException("Unrecognized Java version: "+version);
 			}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
index 4590978..6523f0e 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
@@ -5723,7 +5723,7 @@
  */
 public void testBug298844a() {
 	setFormatLineCommentOnFirstColumn();
-	this.formatterPrefs.insert_new_line_in_empty_method_body = false;
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 	String source = 
 		"public class X01 {\n" + 
 		"public X01() {\n" + 
@@ -5739,7 +5739,7 @@
 	);
 }
 public void testBug298844b() {
-	this.formatterPrefs.insert_new_line_in_empty_method_body = false;
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 	String source = 
 		"public class X02 {\n" + 
 		"public void foo() {\n" + 
@@ -11767,7 +11767,7 @@
  * https://bugs.eclipse.org/475793 - [formatter] Incorrect whitespace after lambda block
  */
 public void testBug475793() {
-	this.formatterPrefs.insert_new_line_in_empty_block = false;
+	this.formatterPrefs.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 	String source =
 		"public class C {\r\n" + 
 		"	public void f() {\r\n" + 
@@ -11786,7 +11786,7 @@
  * https://bugs.eclipse.org/475746 - [formatter] insert-space rules sometimes ignored with anonymous subclass or when Annotations present
  */
 public void testBug475746() {
-	this.formatterPrefs.insert_new_line_in_empty_block = false;
+	this.formatterPrefs.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 	this.formatterPrefs.insert_space_after_opening_paren_in_method_invocation = true;
 	this.formatterPrefs.insert_space_before_closing_paren_in_method_invocation = true;
 	this.formatterPrefs.insert_space_after_opening_paren_in_method_declaration = true;
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
index bd7bb18..f027f9b 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
@@ -645,7 +645,7 @@
 	public void test041() {
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_type_declaration = false;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test041", "A.java");//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -653,7 +653,7 @@
 	public void test042() {
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.number_of_empty_lines_to_preserve = 0;
-		preferences.insert_new_line_in_empty_type_declaration = false;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		preferences.insert_space_before_opening_brace_in_block = true;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test042", "A.java");//$NON-NLS-1$ //$NON-NLS-2$
@@ -662,7 +662,7 @@
 	public void test043() {
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_type_declaration = false;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test043", "A.java");//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -1940,10 +1940,10 @@
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.number_of_empty_lines_to_preserve = 0;
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = false;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = false;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test173", "A.java", CodeFormatter.K_CLASS_BODY_DECLARATIONS);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -1954,10 +1954,10 @@
 	public void test174() {
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = false;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = false;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test174", "A.java", CodeFormatter.K_CLASS_BODY_DECLARATIONS);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -1969,10 +1969,9 @@
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.number_of_empty_lines_to_preserve = 0;
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = false;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = true;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test175", "A.java", CodeFormatter.K_CLASS_BODY_DECLARATIONS);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -1983,10 +1982,9 @@
 	public void test176() {
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = false;
-		preferences.insert_new_line_in_empty_method_body = true;
-		preferences.insert_new_line_in_empty_block = false;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test176", "A.java", CodeFormatter.K_CLASS_BODY_DECLARATIONS);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -1997,10 +1995,9 @@
 	public void test177() {
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = false;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = false;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test177", "A.java", CodeFormatter.K_COMPILATION_UNIT);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -2011,10 +2008,9 @@
 	public void test178() {
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = true;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = false;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test178", "A.java", CodeFormatter.K_COMPILATION_UNIT);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -2025,10 +2021,9 @@
 	public void test179() {
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = true;
-		preferences.insert_new_line_in_empty_type_declaration = true;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = false;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test179", "A.java", CodeFormatter.K_COMPILATION_UNIT);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -2039,10 +2034,9 @@
 	public void test180() {
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = false;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = false;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test180", "A.java", CodeFormatter.K_COMPILATION_UNIT);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -4293,10 +4287,9 @@
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.number_of_empty_lines_to_preserve = 0;
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = false;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = false;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test319", "A.java", CodeFormatter.K_CLASS_BODY_DECLARATIONS);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -4305,10 +4298,9 @@
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.number_of_empty_lines_to_preserve = 0;
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = false;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = false;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test320", "A.java", CodeFormatter.K_CLASS_BODY_DECLARATIONS);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -4317,10 +4309,9 @@
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.number_of_empty_lines_to_preserve = 0;
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = false;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = false;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test321", "A.java", CodeFormatter.K_CLASS_BODY_DECLARATIONS);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -4329,10 +4320,9 @@
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.number_of_empty_lines_to_preserve = 0;
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = false;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = true;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test322", "A.java", CodeFormatter.K_CLASS_BODY_DECLARATIONS);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -4341,10 +4331,10 @@
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getEclipse21Settings());
 		preferences.number_of_empty_lines_to_preserve = 0;
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_anonymous_type_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = false;
-		preferences.insert_new_line_in_empty_method_body = false;
-		preferences.insert_new_line_in_empty_block = false;
+		preferences.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test323", "A.java", CodeFormatter.K_CLASS_BODY_DECLARATIONS);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -4614,7 +4604,7 @@
 		preferences.tab_char = DefaultCodeFormatterOptions.SPACE;
 		preferences.blank_lines_before_method = 1;
 		preferences.blank_lines_before_first_class_body_declaration = 1;
-		preferences.insert_new_line_in_empty_method_body = false;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test347", "A.java", CodeFormatter.K_COMPILATION_UNIT);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -4631,7 +4621,7 @@
 		preferences.tab_char = DefaultCodeFormatterOptions.SPACE;
 		preferences.blank_lines_before_method = 1;
 		preferences.blank_lines_before_first_class_body_declaration = 1;
-		preferences.insert_new_line_in_empty_method_body = false;
+		preferences.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences);
 		runTest(codeFormatter, "test348", "A.java", CodeFormatter.K_COMPILATION_UNIT);//$NON-NLS-1$ //$NON-NLS-2$
 	}
@@ -7273,9 +7263,9 @@
 		Map options = DefaultCodeFormatterConstants.getJavaConventionsSettings();
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(options);
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_type_declaration = true;
-		preferences.insert_new_line_in_empty_enum_constant = false;
-		preferences.insert_new_line_in_empty_enum_declaration = false;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		preferences.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
         preferences.tab_size = 4;
 		Hashtable javaCoreOptions = JavaCore.getOptions();
 		try {
@@ -7303,9 +7293,9 @@
 		Map options = DefaultCodeFormatterConstants.getJavaConventionsSettings();
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(options);
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_type_declaration = true;
-		preferences.insert_new_line_in_empty_enum_constant = false;
-		preferences.insert_new_line_in_empty_enum_declaration = true;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		preferences.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
         preferences.tab_size = 4;
 		Hashtable javaCoreOptions = JavaCore.getOptions();
 		try {
@@ -7333,9 +7323,9 @@
 		Map options = DefaultCodeFormatterConstants.getJavaConventionsSettings();
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(options);
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_type_declaration = true;
-		preferences.insert_new_line_in_empty_enum_constant = true;
-		preferences.insert_new_line_in_empty_enum_declaration = false;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		preferences.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		preferences.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
         preferences.tab_size = 4;
 		Hashtable javaCoreOptions = JavaCore.getOptions();
 		try {
@@ -7363,9 +7353,9 @@
 		Map options = DefaultCodeFormatterConstants.getJavaConventionsSettings();
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(options);
 		preferences.tab_char = DefaultCodeFormatterOptions.TAB;
-		preferences.insert_new_line_in_empty_type_declaration = true;
-		preferences.insert_new_line_in_empty_enum_constant = true;
-		preferences.insert_new_line_in_empty_enum_declaration = true;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		preferences.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		preferences.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
         preferences.tab_size = 4;
 		Hashtable javaCoreOptions = JavaCore.getOptions();
 		try {
@@ -8970,8 +8960,8 @@
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(options);
 		preferences.indent_body_declarations_compare_to_annotation_declaration_header = false;
 		preferences.indent_body_declarations_compare_to_type_header = true;
-		preferences.insert_new_line_in_empty_annotation_declaration = false;
-		preferences.insert_new_line_in_empty_type_declaration = true;
+		preferences.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
 		Hashtable javaCoreOptions = JavaCore.getOptions();
 		try {
 			Hashtable newJavaCoreOptions = JavaCore.getOptions();
@@ -8996,8 +8986,8 @@
 		DefaultCodeFormatterOptions preferences = new DefaultCodeFormatterOptions(options);
 		preferences.indent_body_declarations_compare_to_annotation_declaration_header = true;
 		preferences.indent_body_declarations_compare_to_type_header = false;
-		preferences.insert_new_line_in_empty_annotation_declaration = true;
-		preferences.insert_new_line_in_empty_type_declaration = false;
+		preferences.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		preferences.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
 		Hashtable javaCoreOptions = JavaCore.getOptions();
 		try {
 			Hashtable newJavaCoreOptions = JavaCore.getOptions();
@@ -14372,4 +14362,199 @@
 	String input = getCompilationUnit("Formatter", "", "test131292", "in.java").getSource();
 	formatSource(input, getCompilationUnit("Formatter", "", "test131292", "F_out.java").getSource());
 }
+
+/**
+ * https://bugs.eclipse.org/205973 - [formatter] Allow to keep simple methods on one line (for exemple simple getter or setter)
+ */
+public void testBug205973a() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_if_then_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_loop_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_simple_getter_setter_on_one_line = false;
+	this.formatterPrefs.keep_guardian_clause_on_one_line = false;
+	String input = getCompilationUnit("Formatter", "", "test205973", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test205973", "A_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/205973 - [formatter] Allow to keep simple methods on one line (for exemple simple getter or setter)
+ */
+public void testBug205973b() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_if_then_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM;
+	this.formatterPrefs.keep_loop_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM;
+	this.formatterPrefs.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_simple_getter_setter_on_one_line = true;
+	this.formatterPrefs.keep_guardian_clause_on_one_line = false;
+	String input = getCompilationUnit("Formatter", "", "test205973", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test205973", "B_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/205973 - [formatter] Allow to keep simple methods on one line (for exemple simple getter or setter)
+ */
+public void testBug205973c() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM;
+	this.formatterPrefs.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM;
+	this.formatterPrefs.keep_if_then_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_loop_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM;
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_simple_getter_setter_on_one_line = false;
+	this.formatterPrefs.keep_guardian_clause_on_one_line = true;
+	String input = getCompilationUnit("Formatter", "", "test205973", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test205973", "C_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/205973 - [formatter] Allow to keep simple methods on one line (for exemple simple getter or setter)
+ */
+public void testBug205973d() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_if_then_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM;
+	this.formatterPrefs.keep_loop_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM;
+	this.formatterPrefs.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM;
+	this.formatterPrefs.keep_simple_getter_setter_on_one_line = false;
+	this.formatterPrefs.keep_guardian_clause_on_one_line = false;
+	String input = getCompilationUnit("Formatter", "", "test205973", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test205973", "D_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/205973 - [formatter] Allow to keep simple methods on one line (for exemple simple getter or setter)
+ */
+public void testBug205973e() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_if_then_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_loop_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_simple_getter_setter_on_one_line = true;
+	this.formatterPrefs.keep_guardian_clause_on_one_line = true;
+	String input = getCompilationUnit("Formatter", "", "test205973", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test205973", "E_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/205973 - [formatter] Allow to keep simple methods on one line (for exemple simple getter or setter)
+ */
+public void testBug205973f() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_if_then_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_loop_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM;
+	this.formatterPrefs.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_simple_getter_setter_on_one_line = false;
+	this.formatterPrefs.keep_guardian_clause_on_one_line = false;
+	String input = getCompilationUnit("Formatter", "", "test205973", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test205973", "F_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/205973 - [formatter] Allow to keep simple methods on one line (for exemple simple getter or setter)
+ */
+public void testBug205973g() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_if_then_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM;
+	this.formatterPrefs.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_loop_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM;
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_simple_getter_setter_on_one_line = false;
+	this.formatterPrefs.keep_guardian_clause_on_one_line = false;
+	String input = getCompilationUnit("Formatter", "", "test205973", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test205973", "G_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/205973 - [formatter] Allow to keep simple methods on one line (for exemple simple getter or setter)
+ */
+public void testBug205973h() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_PRESERVE;
+	this.formatterPrefs.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_PRESERVE;
+	this.formatterPrefs.keep_if_then_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_PRESERVE;
+	this.formatterPrefs.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_PRESERVE;
+	this.formatterPrefs.keep_loop_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_PRESERVE;
+	this.formatterPrefs.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+	this.formatterPrefs.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_PRESERVE;
+	this.formatterPrefs.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_PRESERVE;
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_PRESERVE;
+	this.formatterPrefs.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_PRESERVE;
+	this.formatterPrefs.keep_simple_getter_setter_on_one_line = false;
+	this.formatterPrefs.keep_guardian_clause_on_one_line = false;
+	this.formatterPrefs.align_type_members_on_columns = true;
+	this.formatterPrefs.align_variable_declarations_on_columns = true;
+	this.formatterPrefs.align_assignment_statements_on_columns = true;
+	String input = getCompilationUnit("Formatter", "", "test205973", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test205973", "H_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/205973 - [formatter] Allow to keep simple methods on one line (for exemple simple getter or setter)
+ */
+public void testBug205973i() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.page_width = 50;
+	this.formatterPrefs.use_tabs_only_for_leading_indentations = true;
+	this.formatterPrefs.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_if_then_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_loop_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+	this.formatterPrefs.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	this.formatterPrefs.keep_simple_getter_setter_on_one_line = false;
+	this.formatterPrefs.keep_guardian_clause_on_one_line = false;
+	String input = getCompilationUnit("Formatter", "", "test205973", "in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test205973", "I_out.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/205973 - [formatter] Allow to keep simple methods on one line (for exemple simple getter or setter)
+ */
+public void testBug205973j() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+	String input = getCompilationUnit("Formatter", "", "test205973", "J_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test205973", "J_out.java").getSource());
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
index 491e60e..1ad40ca 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
@@ -3495,6 +3495,16 @@
 				IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
 				null);
 		} catch (CoreException e) {
+			logError("exception occurred while waiting on indexing", e);
+		}
+	}
+
+	private static void logError(String errorMessage, CoreException e) {
+		Plugin plugin = JavaCore.getPlugin();
+		if (plugin != null) {
+			ILog log = plugin.getLog();
+			Status status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, errorMessage, e);
+			log.log(status);
 		}
 	}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java
index 607c65b..ba4462e 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java
@@ -25,6 +25,7 @@
 import org.eclipse.core.filesystem.URIUtil;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IProjectDescription;
 import org.eclipse.core.resources.IResource;
@@ -37,6 +38,7 @@
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.jdt.core.IBuffer;
 import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaProject;
@@ -1903,12 +1905,18 @@
 	}
 	if (isJRE12) return;
 	try {
-		createJava9Project("Test", new String[]{"src"});
+		IJavaProject prj = createJava9Project("Test", new String[]{"src"});
 		String moduleSrc =
 			"module test {\n" +
 			"	requires oracle.net;\n" +
 			"}\n";
 		createFile("/Test/src/module-info.java", moduleSrc);
+		prj.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+		IMarker[] markers = prj.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+		if (markers.length == 1 && markers[0].toString().contains("oracle.net cannot be resolved to a module")) {
+			System.out.println("Skipping "+getClass().getName()+".testModule2() because module oracle.net is unavailable");
+			return; // oracle.net is missing from openjdk builds
+		}
 		ICompilationUnit unit = getCompilationUnit("/Test/src/module-info.java");
 		int start = moduleSrc.indexOf("oracle.net");
 		int length = "oracle.net".length();
@@ -1927,4 +1935,55 @@
 		deleteProject("Test");
 	}
 }
+public void testModule2b() throws CoreException, IOException {
+	if (!isJRE9) {
+		System.err.println(this.getClass().getName()+'.'+getName()+" needs a Java 9 JRE - skipped");
+		return;
+	}
+	try {
+		// create project with incomplete source attachment:
+		String javaHome = System.getProperty("java.home") + File.separator;
+		Path bootModPath = new Path(javaHome +"/lib/jrt-fs.jar");
+		createSourceZip(
+				new String[] {
+					"java.base/module-info.java",
+					"module java.base {}\n",
+					"java.se.ee/module-info.java",
+					"module java.se.ee {}\n"
+				},
+				getWorkspacePath()+"/Test/src.zip");
+		Path sourceAttachment = new Path("/Test/src.zip");
+		IClasspathEntry jrtEntry;
+		jrtEntry = JavaCore.newLibraryEntry(bootModPath, sourceAttachment, null, null, null, false);
+		IJavaProject project = this.createJavaProject("Test", new String[] {"src"}, new String[0],
+				new String[0], "bin", "9");
+		IClasspathEntry[] old = project.getRawClasspath();
+		IClasspathEntry[] newPath = new IClasspathEntry[old.length +1];
+		System.arraycopy(old, 0, newPath, 0, old.length);
+		newPath[old.length] = jrtEntry;
+		project.setRawClasspath(newPath, null);
+		//
+		String moduleSrc =
+			"module test {\n" +
+			"	requires java.desktop;\n" +
+			"}\n";
+		createFile("/Test/src/module-info.java", moduleSrc);
+		ICompilationUnit unit = getCompilationUnit("/Test/src/module-info.java");
+		int start = moduleSrc.indexOf("java.desktop");
+		int length = "java.desktop".length();
+		IJavaElement[] elements = unit.codeSelect(start, length);
+		assertEquals("expected #elements", 1, elements.length);
+
+		IModuleDescription javaDesktop = (IModuleDescription) elements[0];
+		IModularClassFile cf = (IModularClassFile) javaDesktop.getClassFile();
+		assertSourceEquals(
+			"Unexpected source for class file java.desktop/module-info.class",
+			null,
+			cf.getSource());
+		ISourceRange javadocRange = javaDesktop.getJavadocRange();
+		assertEquals("javadoc from source", null, javadocRange);
+	} finally {
+		deleteProject("Test");
+	}
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Bug376673Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Bug376673Test.java
new file mode 100644
index 0000000..010f0de
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Bug376673Test.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jdt.core.IJavaProject;
+
+import junit.framework.Test;
+
+public class Bug376673Test extends ModifyingResourceTests {
+
+	public Bug376673Test(String name) {
+		super(name);
+		this.endChar = "";
+	}
+
+	public static Test suite() {
+		return buildModelTestSuite(Bug376673Test.class);
+	}
+
+	/**
+     * An extra test for bug 413114 in the context of bug 376673.
+     * We want to know whether we can compile with when using a class from a jar as created in
+     * {@link org.eclipse.jdt.core.tests.model.JavaSearchBugsTests2#testBug376673e()}.
+	 */
+	public void testBug376673() throws Exception {
+		try {
+			if ("macosx".equals(System.getProperty("osgi.os"))) {
+				return;
+			}
+			IJavaProject p = createJavaProject("P", new String[] { "src" }, new String[] { "/P/lib376673.jar", "JCL17_LIB" }, "bin", "1.7");
+
+			org.eclipse.jdt.core.tests.util.Util.createJar(
+					new String[] { "p\uD842\uDF9F/i\uD842\uDF9F/Test.java",
+							"package p\uD842\uDF9F.i\uD842\uDF9F;\n" + "public class Test{}\n" },
+					p.getProject().getLocation().append("lib376673.jar").toOSString(), "1.7");
+
+			createFolder("/P/src/pkg");
+			String[] classFileContent = new String[] {
+					"package pkg;",
+					"class UseJarClass {",
+					"	public p\uD842\uDF9F.i\uD842\uDF9F.Test test;",
+					"}",
+			};
+			IFile file = createFile("/P/src/pkg/UseJarClass.java", String.join(System.lineSeparator(), classFileContent), "UTF-8");
+			file.setCharset("UTF-8", null);
+			refresh(p);
+			waitForAutoBuild();
+			waitUntilIndexesReady();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			List<String> errors = new ArrayList<>();
+			StringBuilder markersToString = new StringBuilder();
+			for (IMarker marker : markers) {
+				
+				Integer severity = (Integer) marker.getAttribute(IMarker.SEVERITY);
+				String message = (String) marker.getAttribute(IMarker.MESSAGE);
+				if (severity.intValue() == IMarker.SEVERITY_ERROR) {
+					errors.add(message);
+				}
+				
+				markersToString.append("Marker with severity: ");
+				markersToString.append(severity);
+				markersToString.append(", and message: ");
+				markersToString.append(message);
+				markersToString.append(", at location: ");
+				markersToString.append(marker.getAttribute(IMarker.LOCATION));
+				markersToString.append(", at line: ");
+				markersToString.append(marker.getAttribute(IMarker.LINE_NUMBER));
+			}
+			assertEquals("expected no markers on test project, all markers are:" + System.lineSeparator() + markersToString,
+					Collections.emptyList(), errors);
+		} finally {
+			deleteProject("P");
+		}
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaCoreOptionsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaCoreOptionsTests.java
index e7d0003..b1dee23 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaCoreOptionsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaCoreOptionsTests.java
@@ -126,6 +126,9 @@
 	assertTrue(JavaCore.compareJavaVersions("9", "9.1.2") == 0);
 	assertTrue(JavaCore.compareJavaVersions("12", "11") > 0);
 	assertTrue(JavaCore.compareJavaVersions("12", "1.5") > 0);
+	String latest = JavaCore.latestSupportedJavaVersion();
+	String latestPlus = "" + (Integer.parseInt(latest) + 1);
+	assertTrue(JavaCore.compareJavaVersions(latest, latestPlus) == 0);
 }
 }
 
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java
index d08d5a1..a4fe9ca 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
index c28aa90..2c92682 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
@@ -41,6 +41,7 @@
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.IProblemRequestor;
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.WorkingCopyOwner;
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.CompilationUnit;
@@ -94,6 +95,16 @@
 		deleteProject("P1");
 	}
 	
+	IClasspathAttribute[] moduleAttribute() {
+		return new IClasspathAttribute[] { JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") };
+	}
+	void addModularProjectEntry(IJavaProject project, IJavaProject depProject) throws JavaModelException {
+		addClasspathEntry(project, JavaCore.newProjectEntry(depProject.getPath(), null, false, moduleAttribute(), false));
+	}
+	void addModularLibraryEntry(IJavaProject project, String libraryPath) throws JavaModelException {
+		addLibraryEntry(project, new Path(libraryPath), null, null, null, null, moduleAttribute(), false);	
+	}
+
 	// Test that the java.base found as a module package fragment root in the project 
 	public void test001() throws CoreException {
 		if (!isJRE9) return;
@@ -1837,8 +1848,8 @@
 			deleteProject("com.greetings");
 		}
 	}
-	// Changes to implicit dependencies should be reflected
-	public void test_ModuleSourcePath_implicitdeps2() throws CoreException {
+	// Changes to implicit dependencies should be reflected // FIXME: container JavaCore.MODULE_PATH_CONTAINER_ID is unreliable
+	public void _test_ModuleSourcePath_implicitdeps2() throws CoreException {
 		if (!isJRE9) return;
 		try {
 			String[] sources = new String[] {
@@ -6279,21 +6290,28 @@
 		if (!isJRE9 || isJRE12) return;
 		ClasspathJrt.resetCaches();
 		try {
-			IJavaProject javaProject = createJava9Project("mod1", new String[] {"src"});
+			// jdk.rmic is not be visible to code in an unnamed module, but using requires we can see the module.
+			// only, there's nothing exported from it (which is why JEP 261 hides it from unnamed), so we --add-reads:
+			IClasspathAttribute[] attrs = new IClasspathAttribute[] {
+				JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "jdk.rmic/sun.rmi.rmic=mod1")
+			};
+			IJavaProject javaProject = createJava9ProjectWithJREAttributes("mod1", new String[] {"src"}, attrs);
 
 			String srcMod =
-				"@SuppressWarnings(\"removal\")\n" + // javax.xml.ws.annotation is deprecated for removal
 				"module mod1 {\n" + 
 				"	exports com.mod1.pack1;\n" + 
-				"	requires java.xml.ws.annotation;\n" + 
+				"	requires jdk.rmic;\n" + 
 				"}";
 			createFile("/mod1/src/module-info.java", 
 				srcMod);
 			createFolder("/mod1/src/com/mod1/pack1");
 			String srcX =
 				"package com.mod1.pack1;\n" +
-				"@javax.annotation.Generated(\"com.acme.generator.CodeGen\")\n" +
+				"import sun.rmi.rmic.Main;\n" +
 				"public class Dummy {\n" +
+				"	String test() {\n" +
+				"		return Main.getString(\"in\");\n" +
+				"	}\n" +
 				"}";
 			createFile("/mod1/src/com/mod1/pack1/Dummy.java", srcX);
 
@@ -6318,6 +6336,92 @@
 		}
 	}
 
+	public void testBug526054b() throws Exception {
+		if (!isJRE9) return;
+		ClasspathJrt.resetCaches();
+		try {
+			// one project can see jdk.rmic/sun.rmi.rmic
+			IClasspathAttribute[] attrs = new IClasspathAttribute[] {
+				JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "jdk.rmic/sun.rmi.rmic=mod1")
+			};
+			createJava9ProjectWithJREAttributes("mod1", new String[] {"src"}, attrs);
+
+			String srcMod1 =
+				"module mod1 {\n" + 
+				"	exports com.mod1.pack1;\n" + 
+				"	requires jdk.rmic;\n" + 
+				"}";
+			createFile("/mod1/src/module-info.java", 
+				srcMod1);
+			createFolder("/mod1/src/com/mod1/pack1");
+			String srcX1 =
+				"package com.mod1.pack1;\n" +
+				"import sun.rmi.rmic.Constants;\n" + // this should never be complained against due to above add-exports.
+				"public class Dummy implements Constants {\n" +
+				"}";
+			createFile("/mod1/src/com/mod1/pack1/Dummy.java", srcX1);
+			
+			// second project cannot see jdk.rmic/sun.rmi.rmic:
+			createJava9Project("mod2", new String[] {"src"});
+
+			String srcMod2 =
+				"module mod2 {\n" + 
+				"	exports com.mod2.pack1;\n" + 
+				"	requires jdk.rmic;\n" + 
+				"}";
+			createFile("/mod2/src/module-info.java", 
+				srcMod2);
+			createFolder("/mod2/src/com/mod2/pack1");
+			String srcX2 =
+				"package com.mod2.pack1;\n" +
+				"import sun.rmi.rmic.Main;\n" +
+				"public class Dummy {\n" +
+				"	String test() {\n" +
+				"		return Main.getString(\"in\");\n" +
+				"	}\n" +
+				"}";
+			createFile("/mod2/src/com/mod2/pack1/Dummy.java", srcX2);
+
+			// check first:
+			this.problemRequestor.initialize(srcX1.toCharArray());
+			getWorkingCopy("/mod1/src/com/mod1/pack1/Dummy.java", srcX1, true);
+			assertProblems("Dummy in mod1 should have no problems",
+					"----------\n" + 
+					"----------\n",
+					this.problemRequestor);
+
+			// check second:
+			this.problemRequestor.initialize(srcX2.toCharArray());
+			getWorkingCopy("/mod2/src/com/mod2/pack1/Dummy.java", srcX2, true);
+			assertProblems("Dummy in mod2 should have problems",
+					"----------\n" + 
+					"1. ERROR in /mod2/src/com/mod2/pack1/Dummy.java (at line 2)\n" + 
+					"	import sun.rmi.rmic.Main;\n" + 
+					"	       ^^^^^^^^^^^^^^^^^\n" + 
+					"The type sun.rmi.rmic.Main is not accessible\n" + 
+					"----------\n" + 
+					"2. ERROR in /mod2/src/com/mod2/pack1/Dummy.java (at line 5)\n" + 
+					"	return Main.getString(\"in\");\n" + 
+					"	       ^^^^\n" + 
+					"Main cannot be resolved\n" + 
+					"----------\n",
+					this.problemRequestor);
+
+			// check both in a combined build
+			getWorkspace().build(IncrementalProjectBuilder.CLEAN_BUILD, null);
+			getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = getWorkspace().getRoot().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers",
+					"The type sun.rmi.rmic.Main is not accessible\n" + 
+					"Main cannot be resolved",
+					markers);
+		} finally {
+			deleteProject("mod1");
+			deleteProject("mod2");
+		}
+	}
+
 	public void testBug525918() throws CoreException {
 		if (!isJRE9) return;
 		try {
@@ -7039,6 +7143,173 @@
 			this.deleteProject("Bug540904");
 		}
 	}
+	public void testBug540788() throws Exception {
+		if (!isJRE9) return;
+		try {
+			// project common:
+			IJavaProject common = createJava9Project("Bug540788.common", new String[] { "src/main/java" });
+			createSourceFiles(common,
+					new String[] {
+						"src/main/java/module-info.java",
+						"module org.sheepy.common {\n" + 
+						"	requires transitive org.eclipse.emf.common;\n" + 
+						"	requires transitive org.eclipse.emf.ecore;\n" + 
+						"}\n"
+					});
+			IFolder libs = createFolder("/Bug540788.common/libs");
+			String emfCommonPath = libs.getLocation()+"/org.eclipse.emf.common.jar";
+			Util.createJar(
+					new String[] {
+							"src/org/eclipse/emf/common/Foo.java",
+							"package org.eclipse.emf.common;\n" +
+							"public interface Foo {\n" +
+							"}",
+					},
+					null,
+					new HashMap<>(),
+					null,
+					emfCommonPath);
+			addModularLibraryEntry(common, emfCommonPath);
+			String ecorePath = libs.getLocation()+"/org.eclipse.emf.ecore.jar";
+			Util.createJar(
+					new String[] {
+						"src/org/eclipse/emf/ecore/EObject.java",
+						"package org.eclipse.emf.ecore;\n" +
+						"public interface EObject {\n" +
+						"}",
+					},
+					null,
+					new HashMap<>(),
+					null,
+					ecorePath);
+			addModularLibraryEntry(common, ecorePath);
+			// project vulkan:
+			IJavaProject vulkan = createJava9Project("Bug540788.vulkan", new String[] { "src/main/java" });
+			createSourceFiles(vulkan,
+					new String[] {
+						"src/main/java/module-info.java",
+						"module org.sheepy.vulkan {\n" + 
+						"	requires transitive org.sheepy.common;\n" + 
+						"	exports org.sheepy.vulkan.model.resource;\n" + 
+						"}\n",
+						"src/main/java/org/sheepy/vulkan/model/resource/Resource.java",
+						"package org.sheepy.vulkan.model.resource;\n" + 
+						"import org.eclipse.emf.ecore.EObject;\n" + 
+						"public interface Resource extends EObject {\n" + 
+						"}\n",
+						"src/main/java/org/sheepy/vulkan/model/resource/VulkanBuffer.java",
+						"package org.sheepy.vulkan.model.resource;\n" + 
+						"public interface VulkanBuffer extends Resource {\n" + 
+						"}\n",
+					});
+			addModularProjectEntry(vulkan, common);
+			addModularLibraryEntry(vulkan, emfCommonPath);
+			addModularLibraryEntry(vulkan, ecorePath);
+			// project vulkan.demo
+			IJavaProject vulkan_demo = createJava9Project("Bug540788.vulkan.demo", new String[] { "src/main/java" });
+			createSourceFiles(vulkan_demo,
+					new String[] {
+						"src/main/java/module-info.java",
+						"module org.sheepy.vulkan.demo {\n" + 
+						"	exports org.sheepy.vulkan.demo.model;\n" + 
+						"	requires org.sheepy.vulkan;\n" + 
+						"}\n",
+						"src/main/java/org/sheepy/vulkan/demo/model/UniformBuffer.java",
+						"package org.sheepy.vulkan.demo.model;\n" + 
+						"import org.sheepy.vulkan.model.resource.VulkanBuffer;\n" + 
+						"public interface UniformBuffer extends VulkanBuffer {\n" + 
+						"}\n",
+					});
+			addModularProjectEntry(vulkan_demo, vulkan);
+			addModularProjectEntry(vulkan_demo, common);
+			addModularLibraryEntry(vulkan_demo, emfCommonPath);
+			addModularLibraryEntry(vulkan_demo, ecorePath);
+			
+			getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = vulkan_demo.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "", markers);
+		} finally {
+			deleteProject("Bug540788.common");
+			deleteProject("Bug540788.vulkan");
+			deleteProject("Bug540788.vulkan.demo");
+		}
+	}
+	public void testBug541015() throws Exception {
+		try {
+			IJavaProject m1 = createJava9Project("m1", new String[] { "src" });
+			createSourceFiles(m1,
+					new String[] {
+						"src/module-info.java",
+						"module m1 { exports org.p1; }\n",
+						"src/org/p1/T1.java",
+						"package org.p1;\n" +
+						"public class T1 {}\n"
+					});
+			IJavaProject m2 = createJava9Project("m2", new String[] { "src" });
+			createSourceFiles(m2,
+					new String[] {
+						"src/module-info.java",
+						"module m2 { exports org.p1; }\n",
+						"src/org/p1/T1.java",
+						"package org.p1;\n" +
+						"public class T1 {}\n"
+					});
+			IJavaProject m3 = createJava9Project("m3", new String[] { "src" });
+			createSourceFiles(m3,
+					new String[] {
+						"src/module-info.java",
+						"module m3 { exports org.p1; }\n",
+						"src/org/p1/T1.java",
+						"package org.p1;\n" +
+						"public class T1 {}\n"
+					});
+			IJavaProject unnamed = createJava9Project("unnamed", new String[] { "src" });
+			String testSource = "package test;\n" +
+			"import org.p1.T1;\n" +
+			"public class Test {\n" +
+			"	T1 t1;\n" +
+			"}\n";
+			createSourceFiles(unnamed,
+					new String[] {
+						"src/test/Test.java",
+						testSource
+					});
+			addModularProjectEntry(unnamed, m1);
+			addModularProjectEntry(unnamed, m2);
+			addModularProjectEntry(unnamed, m3);
+			
+			getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = unnamed.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers",
+					"The import org.p1.T1 cannot be resolved\n" + 
+					"T1 cannot be resolved to a type",
+					markers);
+			
+			char[] sourceChars = testSource.toCharArray();
+			this.problemRequestor.initialize(sourceChars);
+			getCompilationUnit("/unnamed/src/test/Test.java").getWorkingCopy(this.wcOwner, null);
+			assertProblems(
+					"Unexpected problems",
+					"----------\n" + 
+					"1. ERROR in /unnamed/src/test/Test.java (at line 2)\n" + 
+					"	import org.p1.T1;\n" + 
+					"	       ^^^^^^^^^\n" + 
+					"The import org.p1.T1 cannot be resolved\n" + 
+					"----------\n" + 
+					"2. ERROR in /unnamed/src/test/Test.java (at line 4)\n" + 
+					"	T1 t1;\n" + 
+					"	^^\n" + 
+					"T1 cannot be resolved to a type\n" + 
+					"----------\n",
+					this.problemRequestor);
+		} finally {
+			deleteProject("m1");
+			deleteProject("m2");
+			deleteProject("m3");
+			deleteProject("unnamed");
+		}
+	}
 	protected void assertNoErrors() throws CoreException {
 		for (IProject p : getWorkspace().getRoot().getProjects()) {
 			int maxSeverity = p.findMaxProblemSeverity(null, true, IResource.DEPTH_INFINITE);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunJavaSearchTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunJavaSearchTests.java
index 3695005..1333386 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunJavaSearchTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RunJavaSearchTests.java
@@ -71,6 +71,7 @@
 		allClasses.add(JavaSearchScopeTests.class);
 		allClasses.add(MatchingRegionsTest.class);
 		allClasses.add(JavaIndexTests.class);
+		allClasses.add(Bug376673Test.class);
 
 		// Reset forgotten subsets of tests
 		TestCase.TESTS_PREFIX = null;
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/A_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/A_out.java
new file mode 100644
index 0000000..89aa366
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/A_out.java
@@ -0,0 +1,160 @@
+class Example {
+	public void example() {
+		for (int i = 0; i < 10; i++) {}
+		int a = 10;
+		while (a-- > 0) {
+			System.out.println(a);
+		}
+		do {
+			a += 2;
+			System.out.println(a);
+		} while (a < 50);
+	}
+}
+
+class Example {
+	public String example(int a) {
+		if (a < 0) {
+			throw new IllegalArgumentException();
+		}
+		if (a == 0) {
+			return null;
+		}
+		if (false) {}
+		if (a % 3 == 0) {
+			System.out.println("fizz");
+		}
+		if (a % 5 == 0) {
+			System.out.println("buzz");
+			return "";
+		}
+		return Integer.toString(a);
+	}
+}
+
+class Example {
+	Runnable emptyLambda = () -> {};
+	Runnable emptyLambda2 = () -> {};
+	Runnable tinyLambda = () -> {
+		doSomething();
+	};
+	Runnable smallLambda = () -> {
+		doFirstThing();
+		doSecondThing();
+	};
+}
+
+class Example {
+	static {
+	}
+
+	void foo() {
+		if (true) {
+		} else {
+		}
+		synchronized (this) {
+		}
+		try {
+		} finally {
+		}
+
+		labeled: {
+		}
+	}
+}
+
+public class Example {
+	private int something;
+
+	public int getSomething() {
+		return something;
+	}
+
+	public void setSomehing(int something) {
+		this.something = something;
+	}
+
+	public void doNoting() {
+	}
+
+	public void doOneThing() {
+		System.out.println();
+	}
+
+	public void doMoreThings() {
+		something = 4;
+		doOneThing();
+		doOneThing();
+	}
+}
+
+public class EmptyClass {
+}
+
+public class TinyClass {
+	int a;
+}
+
+public class SmallClass {
+	int a;
+	String b;
+}
+
+public class AnonymousClasses {
+	EmptyClass emptyAnonymous = new EmptyClass() {};
+	TinyClass tinyAnonymous = new TinyClass() {
+		String b;
+	};
+	Object o = new SmallClass() {
+		int a;
+
+		int getA() {
+			return a;
+		}
+	};
+}
+
+public enum EmptyEnum {
+}
+
+public enum TinyEnum {
+	A;
+}
+
+public enum SmallEnum {
+	VALUE(0);
+	SmallEnum(int val) {
+	};
+}
+
+public enum EnumConstants {
+	EMPTY {
+	},
+	TINY {
+		int getVal() {
+			return 2;
+		}
+	},
+	SMALL {
+		int val = 3;
+
+		int getVal() {
+			return 3;
+		}
+	};
+	int getVal() {
+		return 1;
+	}
+}
+
+public @interface EmptyInterface {}
+
+public @interface TinyInterface {
+	void run();
+}
+
+public @interface SmallInteface {
+	int toA();
+
+	String toB();
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/B_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/B_out.java
new file mode 100644
index 0000000..4c112b8
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/B_out.java
@@ -0,0 +1,145 @@
+class Example {
+	public void example() {
+		for (int i = 0; i < 10; i++) {}
+		int a = 10;
+		while (a-- > 0) { System.out.println(a); }
+		do {
+			a += 2;
+			System.out.println(a);
+		} while (a < 50);
+	}
+}
+
+class Example {
+	public String example(int a) {
+		if (a < 0) {
+			throw new IllegalArgumentException();
+		}
+		if (a == 0) {
+			return null;
+		}
+		if (false) {
+		}
+		if (a % 3 == 0) {
+			System.out.println("fizz");
+		}
+		if (a % 5 == 0) {
+			System.out.println("buzz");
+			return "";
+		}
+		return Integer.toString(a);
+	}
+}
+
+class Example {
+	Runnable emptyLambda = () -> {};
+	Runnable emptyLambda2 = () -> {};
+	Runnable tinyLambda = () -> { doSomething(); };
+	Runnable smallLambda = () -> {
+		doFirstThing();
+		doSecondThing();
+	};
+}
+
+class Example {
+	static {
+	}
+
+	void foo() {
+		if (true) {
+		} else {
+		}
+		synchronized (this) {
+		}
+		try {
+		} finally {
+		}
+
+		labeled: {
+		}
+	}
+}
+
+public class Example {
+	private int something;
+
+	public int getSomething() { return something; }
+
+	public void setSomehing(int something) { this.something = something; }
+
+	public void doNoting() {
+	}
+
+	public void doOneThing() {
+		System.out.println();
+	}
+
+	public void doMoreThings() {
+		something = 4;
+		doOneThing();
+		doOneThing();
+	}
+}
+
+public class EmptyClass {
+}
+
+public class TinyClass {
+	int a;
+}
+
+public class SmallClass {
+	int a;
+	String b;
+}
+
+public class AnonymousClasses {
+	EmptyClass emptyAnonymous = new EmptyClass() {
+	};
+	TinyClass tinyAnonymous = new TinyClass() {
+		String b;
+	};
+	Object o = new SmallClass() {
+		int a;
+
+		int getA() { return a; }
+	};
+}
+
+public enum EmptyEnum {}
+
+public enum TinyEnum {
+	A;
+}
+
+public enum SmallEnum {
+	VALUE(0);
+	SmallEnum(int val) {
+	};
+}
+
+public enum EnumConstants {
+	EMPTY {},
+	TINY {
+		int getVal() { return 2; }
+	},
+	SMALL {
+		int val = 3;
+
+		int getVal() { return 3; }
+	};
+	int getVal() { return 1; }
+}
+
+public @interface EmptyInterface {
+}
+
+public @interface TinyInterface {
+	void run();
+}
+
+public @interface SmallInteface {
+	int toA();
+
+	String toB();
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/C_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/C_out.java
new file mode 100644
index 0000000..ec05534
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/C_out.java
@@ -0,0 +1,143 @@
+class Example {
+	public void example() {
+		for (int i = 0; i < 10; i++) {
+		}
+		int a = 10;
+		while (a-- > 0) {
+			System.out.println(a);
+		}
+		do {
+			a += 2;
+			System.out.println(a);
+		} while (a < 50);
+	}
+}
+
+class Example {
+	public String example(int a) {
+		if (a < 0) { throw new IllegalArgumentException(); }
+		if (a == 0) { return null; }
+		if (false) {
+		}
+		if (a % 3 == 0) {
+			System.out.println("fizz");
+		}
+		if (a % 5 == 0) {
+			System.out.println("buzz");
+			return "";
+		}
+		return Integer.toString(a);
+	}
+}
+
+class Example {
+	Runnable emptyLambda = () -> {
+	};
+	Runnable emptyLambda2 = () -> {
+	};
+	Runnable tinyLambda = () -> {
+		doSomething();
+	};
+	Runnable smallLambda = () -> {
+		doFirstThing();
+		doSecondThing();
+	};
+}
+
+class Example {
+	static {}
+
+	void foo() {
+		if (true) {} else {}
+		synchronized (this) {}
+		try {} finally {}
+
+		labeled: {}
+	}
+}
+
+public class Example {
+	private int something;
+
+	public int getSomething() {
+		return something;
+	}
+
+	public void setSomehing(int something) {
+		this.something = something;
+	}
+
+	public void doNoting() {}
+
+	public void doOneThing() {
+		System.out.println();
+	}
+
+	public void doMoreThings() {
+		something = 4;
+		doOneThing();
+		doOneThing();
+	}
+}
+
+public class EmptyClass {}
+
+public class TinyClass {
+	int a;
+}
+
+public class SmallClass {
+	int a;
+	String b;
+}
+
+public class AnonymousClasses {
+	EmptyClass emptyAnonymous = new EmptyClass() {};
+	TinyClass tinyAnonymous = new TinyClass() { String b; };
+	Object o = new SmallClass() {
+		int a;
+
+		int getA() {
+			return a;
+		}
+	};
+}
+
+public enum EmptyEnum {}
+
+public enum TinyEnum { A; }
+
+public enum SmallEnum {
+	VALUE(0);
+	SmallEnum(int val) {};
+}
+
+public enum EnumConstants {
+	EMPTY {
+	},
+	TINY {
+		int getVal() {
+			return 2;
+		}
+	},
+	SMALL {
+		int val = 3;
+
+		int getVal() {
+			return 3;
+		}
+	};
+	int getVal() {
+		return 1;
+	}
+}
+
+public @interface EmptyInterface {}
+
+public @interface TinyInterface { void run(); }
+
+public @interface SmallInteface {
+	int toA();
+
+	String toB();
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/D_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/D_out.java
new file mode 100644
index 0000000..a1e2cca
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/D_out.java
@@ -0,0 +1,148 @@
+class Example {
+	public void example() {
+		for (int i = 0; i < 10; i++) {
+		}
+		int a = 10;
+		while (a-- > 0) {
+			System.out.println(a);
+		}
+		do {
+			a += 2;
+			System.out.println(a);
+		} while (a < 50);
+	}
+}
+
+class Example {
+	public String example(int a) {
+		if (a < 0) {
+			throw new IllegalArgumentException();
+		}
+		if (a == 0) {
+			return null;
+		}
+		if (false) {
+		}
+		if (a % 3 == 0) {
+			System.out.println("fizz");
+		}
+		if (a % 5 == 0) {
+			System.out.println("buzz");
+			return "";
+		}
+		return Integer.toString(a);
+	}
+}
+
+class Example {
+	Runnable emptyLambda = () -> {};
+	Runnable emptyLambda2 = () -> {};
+	Runnable tinyLambda = () -> { doSomething(); };
+	Runnable smallLambda = () -> {
+		doFirstThing();
+		doSecondThing();
+	};
+}
+
+class Example {
+	static {}
+
+	void foo() {
+		if (true) {} else {}
+		synchronized (this) {}
+		try {} finally {}
+
+		labeled: {}
+	}
+}
+
+public class Example {
+	private int something;
+
+	public int getSomething() {
+		return something;
+	}
+
+	public void setSomehing(int something) {
+		this.something = something;
+	}
+
+	public void doNoting() {
+	}
+
+	public void doOneThing() {
+		System.out.println();
+	}
+
+	public void doMoreThings() {
+		something = 4;
+		doOneThing();
+		doOneThing();
+	}
+}
+
+public class EmptyClass {}
+
+public class TinyClass { int a; }
+
+public class SmallClass {
+	int a;
+	String b;
+}
+
+public class AnonymousClasses {
+	EmptyClass emptyAnonymous = new EmptyClass() {};
+	TinyClass tinyAnonymous = new TinyClass() { String b; };
+	Object o = new SmallClass() {
+		int a;
+
+		int getA() {
+			return a;
+		}
+	};
+}
+
+public enum EmptyEnum {
+}
+
+public enum TinyEnum {
+	A;
+}
+
+public enum SmallEnum {
+	VALUE(0);
+	SmallEnum(int val) {
+	};
+}
+
+public enum EnumConstants {
+	EMPTY {},
+	TINY {
+		int getVal() {
+			return 2;
+		}
+	},
+	SMALL {
+		int val = 3;
+
+		int getVal() {
+			return 3;
+		}
+	};
+	int getVal() {
+		return 1;
+	}
+}
+
+public @interface EmptyInterface {
+}
+
+public @interface TinyInterface {
+	void run();
+}
+
+public @interface SmallInteface {
+	int toA();
+
+	String toB();
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/E_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/E_out.java
new file mode 100644
index 0000000..60cf56f
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/E_out.java
@@ -0,0 +1,127 @@
+class Example {
+	public void example() {
+		for (int i = 0; i < 10; i++) {}
+		int a = 10;
+		while (a-- > 0) { System.out.println(a); }
+		do { a += 2; System.out.println(a); } while (a < 50);
+	}
+}
+
+class Example {
+	public String example(int a) {
+		if (a < 0) { throw new IllegalArgumentException(); }
+		if (a == 0) { return null; }
+		if (false) {}
+		if (a % 3 == 0) {
+			System.out.println("fizz");
+		}
+		if (a % 5 == 0) {
+			System.out.println("buzz");
+			return "";
+		}
+		return Integer.toString(a);
+	}
+}
+
+class Example {
+	Runnable emptyLambda = () -> {
+	};
+	Runnable emptyLambda2 = () -> {
+	};
+	Runnable tinyLambda = () -> {
+		doSomething();
+	};
+	Runnable smallLambda = () -> {
+		doFirstThing();
+		doSecondThing();
+	};
+}
+
+class Example {
+	static {
+	}
+
+	void foo() {
+		if (true) {
+		} else {
+		}
+		synchronized (this) {
+		}
+		try {
+		} finally {
+		}
+
+		labeled: {
+		}
+	}
+}
+
+public class Example {
+	private int something;
+
+	public int getSomething() { return something; }
+
+	public void setSomehing(int something) { this.something = something; }
+
+	public void doNoting() {}
+
+	public void doOneThing() {
+		System.out.println();
+	}
+
+	public void doMoreThings() {
+		something = 4;
+		doOneThing();
+		doOneThing();
+	}
+}
+
+public class EmptyClass {
+}
+
+public class TinyClass {
+	int a;
+}
+
+public class SmallClass {
+	int a;
+	String b;
+}
+
+public class AnonymousClasses {
+	EmptyClass emptyAnonymous = new EmptyClass() {
+	};
+	TinyClass tinyAnonymous = new TinyClass() {
+		String b;
+	};
+	Object o = new SmallClass() {
+		int a;
+
+		int getA() { return a; }
+	};
+}
+
+public enum EmptyEnum {
+}
+
+public enum TinyEnum {
+	A;
+}
+
+public enum SmallEnum {
+	VALUE(0);
+	SmallEnum(int val) {};
+}
+
+public enum EnumConstants {
+	EMPTY {},
+	TINY { int getVal() { return 2; } },
+	SMALL { int val = 3; int getVal() { return 3; } };
+	int getVal() { return 1; }
+}
+
+public @interface EmptyInterface {}
+
+public @interface TinyInterface { void run(); }
+
+public @interface SmallInteface { int toA(); String toB(); }
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/F_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/F_out.java
new file mode 100644
index 0000000..012f0e3
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/F_out.java
@@ -0,0 +1,142 @@
+class Example {
+	public void example() {
+		for (int i = 0; i < 10; i++) {}
+		int a = 10;
+		while (a-- > 0) { System.out.println(a); }
+		do {
+			a += 2;
+			System.out.println(a);
+		} while (a < 50);
+	}
+}
+
+class Example {
+	public String example(int a) {
+		if (a < 0) { throw new IllegalArgumentException(); }
+		if (a == 0) { return null; }
+		if (false) {}
+		if (a % 3 == 0) { System.out.println("fizz"); }
+		if (a % 5 == 0) { System.out.println("buzz"); return ""; }
+		return Integer.toString(a);
+	}
+}
+
+class Example {
+	Runnable emptyLambda = () -> {
+	};
+	Runnable emptyLambda2 = () -> {
+	};
+	Runnable tinyLambda = () -> {
+		doSomething();
+	};
+	Runnable smallLambda = () -> {
+		doFirstThing();
+		doSecondThing();
+	};
+}
+
+class Example {
+	static {
+	}
+
+	void foo() {
+		if (true) {
+		} else {
+		}
+		synchronized (this) {
+		}
+		try {
+		} finally {
+		}
+
+		labeled: {
+		}
+	}
+}
+
+public class Example {
+	private int something;
+
+	public int getSomething() {
+		return something;
+	}
+
+	public void setSomehing(int something) {
+		this.something = something;
+	}
+
+	public void doNoting() {
+	}
+
+	public void doOneThing() {
+		System.out.println();
+	}
+
+	public void doMoreThings() {
+		something = 4;
+		doOneThing();
+		doOneThing();
+	}
+}
+
+public class EmptyClass {}
+
+public class TinyClass { int a; }
+
+public class SmallClass { int a; String b; }
+
+public class AnonymousClasses {
+	EmptyClass emptyAnonymous = new EmptyClass() {};
+	TinyClass tinyAnonymous = new TinyClass() {
+		String b;
+	};
+	Object o = new SmallClass() {
+		int a;
+
+		int getA() {
+			return a;
+		}
+	};
+}
+
+public enum EmptyEnum {}
+
+public enum TinyEnum { A; }
+
+public enum SmallEnum {
+	VALUE(0);
+	SmallEnum(int val) {
+	};
+}
+
+public enum EnumConstants {
+	EMPTY {},
+	TINY {
+		int getVal() {
+			return 2;
+		}
+	},
+	SMALL {
+		int val = 3;
+
+		int getVal() {
+			return 3;
+		}
+	};
+	int getVal() {
+		return 1;
+	}
+}
+
+public @interface EmptyInterface {
+}
+
+public @interface TinyInterface {
+	void run();
+}
+
+public @interface SmallInteface {
+	int toA();
+
+	String toB();
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/G_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/G_out.java
new file mode 100644
index 0000000..fc1e78c
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/G_out.java
@@ -0,0 +1,121 @@
+class Example {
+	public void example() {
+		for (int i = 0; i < 10; i++) {
+		}
+		int a = 10;
+		while (a-- > 0) {
+			System.out.println(a);
+		}
+		do {
+			a += 2;
+			System.out.println(a);
+		} while (a < 50);
+	}
+}
+
+class Example {
+	public String example(int a) {
+		if (a < 0) { throw new IllegalArgumentException(); }
+		if (a == 0) { return null; }
+		if (false) {}
+		if (a % 3 == 0) { System.out.println("fizz"); }
+		if (a % 5 == 0) {
+			System.out.println("buzz");
+			return "";
+		}
+		return Integer.toString(a);
+	}
+}
+
+class Example {
+	Runnable emptyLambda = () -> {};
+	Runnable emptyLambda2 = () -> {};
+	Runnable tinyLambda = () -> { doSomething(); };
+	Runnable smallLambda = () -> { doFirstThing(); doSecondThing(); };
+}
+
+class Example {
+	static {}
+
+	void foo() {
+		if (true) {} else {}
+		synchronized (this) {}
+		try {} finally {}
+
+		labeled: {}
+	}
+}
+
+public class Example {
+	private int something;
+
+	public int getSomething() { return something; }
+
+	public void setSomehing(int something) { this.something = something; }
+
+	public void doNoting() {}
+
+	public void doOneThing() { System.out.println(); }
+
+	public void doMoreThings() { something = 4; doOneThing(); doOneThing(); }
+}
+
+public class EmptyClass {
+}
+
+public class TinyClass {
+	int a;
+}
+
+public class SmallClass {
+	int a;
+	String b;
+}
+
+public class AnonymousClasses {
+	EmptyClass emptyAnonymous = new EmptyClass() {
+	};
+	TinyClass tinyAnonymous = new TinyClass() {
+		String b;
+	};
+	Object o = new SmallClass() {
+		int a;
+
+		int getA() { return a; }
+	};
+}
+
+public enum EmptyEnum {}
+
+public enum TinyEnum { A; }
+
+public enum SmallEnum {
+	VALUE(0);
+	SmallEnum(int val) {};
+}
+
+public enum EnumConstants {
+	EMPTY {
+	},
+	TINY {
+		int getVal() { return 2; }
+	},
+	SMALL {
+		int val = 3;
+
+		int getVal() { return 3; }
+	};
+	int getVal() { return 1; }
+}
+
+public @interface EmptyInterface {}
+
+public @interface TinyInterface {
+	void run();
+}
+
+public @interface SmallInteface {
+	int toA();
+
+	String toB();
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/H_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/H_out.java
new file mode 100644
index 0000000..9eba7cd
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/H_out.java
@@ -0,0 +1,109 @@
+class Example {
+	public void example() {
+		for (int i = 0; i < 10; i++) {
+		}
+		int a = 10;
+		while (a-- > 0) { System.out.println(a); }
+		do {
+			a += 2;
+			System.out.println(a);
+		} while (a < 50);
+	}
+}
+
+class Example {
+	public String example(int a) {
+		if (a < 0) {
+			throw new IllegalArgumentException();
+		}
+		if (a == 0) { return null; }
+		if (false) {}
+		if (a % 3 == 0) {
+			System.out.println("fizz");
+		}
+		if (a % 5 == 0) { System.out.println("buzz"); return ""; }
+		return Integer.toString(a);
+	}
+}
+
+class Example {
+	Runnable	emptyLambda		= () -> {};
+	Runnable	emptyLambda2	= () -> {
+								};
+	Runnable	tinyLambda		= () -> { doSomething(); };
+	Runnable	smallLambda		= () -> { doFirstThing(); doSecondThing(); };
+}
+
+class Example {
+	static {
+	}
+
+	void foo() {
+		if (true) {
+		} else {
+		}
+		synchronized (this) {
+		}
+		try {
+		} finally {
+		}
+
+		labeled: {
+		}
+	}
+}
+
+public class Example {
+	private int something;
+
+	public int getSomething() { return something; }
+
+	public void setSomehing(int something) { this.something = something; }
+
+	public void doNoting() {}
+
+	public void doOneThing() {
+		System.out.println();
+	}
+
+	public void doMoreThings() { something = 4; doOneThing(); doOneThing(); }
+}
+
+public class EmptyClass {}
+
+public class TinyClass {
+	int a;
+}
+
+public class SmallClass { int a; String b; }
+
+public class AnonymousClasses {
+	EmptyClass	emptyAnonymous	= new EmptyClass() {
+								};
+	TinyClass	tinyAnonymous	= new TinyClass() { String b; };
+	Object		o				= new SmallClass() { int a; int getA() { return a; } };
+}
+
+public enum EmptyEnum {}
+
+public enum TinyEnum {
+	A;
+}
+
+public enum SmallEnum { VALUE(0); SmallEnum(int val) {}; }
+
+public enum EnumConstants {
+	EMPTY {
+	},
+	TINY { int getVal() { return 2; } },
+	SMALL { int val = 3; int getVal() { return 3; } };
+	int getVal() { return 1; }
+}
+
+public @interface EmptyInterface {}
+
+public @interface TinyInterface {
+	void run();
+}
+
+public @interface SmallInteface { int toA(); String toB(); }
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/I_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/I_out.java
new file mode 100644
index 0000000..82d5839
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/I_out.java
@@ -0,0 +1,125 @@
+class Example {
+	public void example() {
+		for (int i = 0; i < 10; i++) {}
+		int a = 10;
+		while (a-- > 0) { System.out.println(a); }
+		do {
+			a += 2;
+			System.out.println(a);
+		} while (a < 50);
+	}
+}
+
+class Example {
+	public String example(int a) {
+		if (a < 0) {
+			throw new IllegalArgumentException();
+		}
+		if (a == 0) { return null; }
+		if (false) {}
+		if (a % 3 == 0) {
+			System.out.println("fizz");
+		}
+		if (a % 5 == 0) {
+			System.out.println("buzz");
+			return "";
+		}
+		return Integer.toString(a);
+	}
+}
+
+class Example {
+	Runnable emptyLambda = () -> {};
+	Runnable emptyLambda2 = () -> {};
+	Runnable tinyLambda = () -> {
+	    doSomething();
+	};
+	Runnable smallLambda = () -> {
+	    doFirstThing();
+	    doSecondThing();
+	};
+}
+
+class Example {
+	static {}
+
+	void foo() {
+		if (true) {} else {}
+		synchronized (this) {}
+		try {} finally {}
+
+		labeled: {}
+	}
+}
+
+public class Example {
+	private int something;
+
+	public int getSomething() {
+		return something;
+	}
+
+	public void setSomehing(int something) {
+		this.something = something;
+	}
+
+	public void doNoting() {}
+
+	public void doOneThing() {
+		System.out.println();
+	}
+
+	public void doMoreThings() {
+		something = 4;
+		doOneThing();
+		doOneThing();
+	}
+}
+
+public class EmptyClass {}
+
+public class TinyClass { int a; }
+
+public class SmallClass { int a; String b; }
+
+public class AnonymousClasses {
+	EmptyClass emptyAnonymous = new EmptyClass() {};
+	TinyClass tinyAnonymous = new TinyClass() {
+		String b;
+	};
+	Object o = new SmallClass() {
+		int a;
+
+		int getA() { return a; }
+	};
+}
+
+public enum EmptyEnum {}
+
+public enum TinyEnum { A; }
+
+public enum SmallEnum {
+	VALUE(0);
+	SmallEnum(int val) {};
+}
+
+public enum EnumConstants {
+	EMPTY {},
+	TINY { int getVal() { return 2; } },
+	SMALL {
+		int val = 3;
+
+		int getVal() { return 3; }
+	};
+	int getVal() { return 1; }
+}
+
+public @interface EmptyInterface {}
+
+public @interface TinyInterface { void run(); }
+
+public @interface SmallInteface {
+	int toA();
+
+	String toB();
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/J_in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/J_in.java
new file mode 100644
index 0000000..41d96d0
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/J_in.java
@@ -0,0 +1,30 @@
+class Example {
+	
+	void method1() {
+		int a;
+	}
+	
+	void method2() {
+		
+		int a;
+		
+		
+	}
+	
+	void method3() {
+		int a; //
+	}
+	
+	void method4() {
+		int a; /* */
+	}
+	
+	void method5() {
+		/* */ int a;
+	}
+	
+	void method6() { int a; /* */ } /* */
+	
+	void method7() { /* */ int a; } /* */
+	
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/J_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/J_out.java
new file mode 100644
index 0000000..2a7ae61
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/J_out.java
@@ -0,0 +1,27 @@
+class Example {
+
+	void method1() { int a; }
+
+	void method2() {
+
+		int a;
+
+	}
+
+	void method3() {
+		int a; //
+	}
+
+	void method4() {
+		int a; /* */
+	}
+
+	void method5() {
+		/* */ int a;
+	}
+
+	void method6() { int a; /* */ } /* */
+
+	void method7() { /* */ int a; } /* */
+
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/in.java
new file mode 100644
index 0000000..bde96a4
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test205973/in.java
@@ -0,0 +1,93 @@
+class Example{
+	public void example() {
+		for (int i = 0; i < 10; i++) {
+		}
+		int a = 10;
+		while (a-- > 0) { System.out.println(a); }
+		do { a += 2;
+		System.out.println(a); } while(a < 50);
+	}
+}
+
+
+class Example {
+	public String example(int a) {
+		if (a < 0) { 
+			throw new IllegalArgumentException(); }
+		if (a == 0) { return null; }
+		if (false) {}
+		if (a % 3 == 0) {
+			System.out.println("fizz"); }
+		if (a % 5 == 0) { System.out.println("buzz"); return ""; }
+		return Integer.toString(a);
+	}
+}
+
+
+class Example {
+	Runnable emptyLambda = () -> {};
+	Runnable emptyLambda2 = () -> {
+	};
+	Runnable tinyLambda = () -> { doSomething(); };
+	Runnable smallLambda = () -> { doFirstThing(); doSecondThing(); };
+}
+
+
+class Example {
+	static {
+	}
+	
+	void foo() {
+		if (true) {} else {}
+		synchronized(this) {}
+		try {} finally {}
+		
+		labeled:{}
+	}
+}
+
+
+public class Example {
+	private int something;
+	public int getSomething() { return something; }
+	public void setSomehing(int something) { this.something = something; }
+	public void doNoting() {}
+	public void doOneThing() { System.out.println();
+	}
+	public void doMoreThings() { something = 4; doOneThing(); doOneThing(); }
+}
+
+
+public class EmptyClass{}
+public class TinyClass{ 
+	int a; }
+public class SmallClass{ int a; String b; }
+
+
+public class AnonymousClasses {
+	EmptyClass emptyAnonymous = new EmptyClass() {
+	};
+	TinyClass tinyAnonymous = new TinyClass() { String b; };
+	Object o = new SmallClass() { int a; int getA() { return a; } };
+}
+
+
+public enum EmptyEnum {}
+public enum TinyEnum{ A;
+}
+public enum SmallEnum{ VALUE(0); SmallEnum(int val) {}; }
+
+
+public enum EnumConstants {
+	EMPTY {
+	},
+	TINY { int getVal() { return 2; }},
+	SMALL { int val = 3; int getVal() { return 3; }};
+	int getVal() { return 1; }
+}
+
+
+public @interface EmptyInterface {}
+public @interface TinyInterface { 
+	void run(); }
+public @interface SmallInteface { int toA(); String toB(); }
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test496/A_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test496/A_out.java
index 7b6cead..19532de 100644
--- a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test496/A_out.java
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test496/A_out.java
@@ -1,7 +1,8 @@
 public class A {
 
     void doX() {
-        if (1 > 0) { return; //
+        if (1 > 0) {
+            return; //
         }
         return;
     }
diff --git a/org.eclipse.jdt.core/.options b/org.eclipse.jdt.core/.options
index a90286e..d558214 100644
--- a/org.eclipse.jdt.core/.options
+++ b/org.eclipse.jdt.core/.options
@@ -1,5 +1,5 @@
 # Turn on debug tracing for org.eclipse.jdt.core plugin
-org.eclipse.jdt.core/debug=true
+org.eclipse.jdt.core/debug=false
 
 # Reports buffer manager activity
 org.eclipse.jdt.core/debug/buffermanager=false
diff --git a/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
index 7cdf9dc..da4229a 100644
--- a/org.eclipse.jdt.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
@@ -16,9 +16,9 @@
  org.eclipse.jdt.core.formatter,
  org.eclipse.jdt.core.index,
  org.eclipse.jdt.core.jdom,
+ org.eclipse.jdt.core.provisional;x-friends:="org.eclipse.jdt.debug.ui,org.eclipse.jdt.launching,org.eclipse.jdt.ui",
  org.eclipse.jdt.core.search,
  org.eclipse.jdt.core.util,
- org.eclipse.jdt.core.provisional;x-friends:="org.eclipse.jdt.debug.ui,org.eclipse.jdt.launching",
  org.eclipse.jdt.internal.codeassist;x-internal:=true,
  org.eclipse.jdt.internal.codeassist.complete;x-internal:=true,
  org.eclipse.jdt.internal.codeassist.impl;x-internal:=true,
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java
index d093225..8498b31 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java
@@ -79,7 +79,9 @@
 	private static final int REPORTED_POTENTIAL_LEAK = 32;
 	// a location independent definitive problem has been reported against this resource:
 	private static final int REPORTED_DEFINITIVE_LEAK = 64;
-	
+	// a local declarations that acts as the element variable of a foreach loop (should never suggest to use t-w-r):
+	private static final int FOREACH_ELEMENT_VAR = 128;
+
 	public static boolean TEST_372319 = false; // see https://bugs.eclipse.org/372319
 
 	/**
@@ -449,9 +451,9 @@
 					if (rhsTrackVar.originalBinding != null)
 						local.closeTracker = rhsTrackVar;			//		a.: let fresh LHS share it
 					if (rhsTrackVar.currentAssignment == location) {
-						// pre-set tracker from lhs - passed from outside?
+						// pre-set tracker from lhs - passed from outside (or foreach)?
 						// now it's a fresh resource
-						rhsTrackVar.globalClosingState &= ~(SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE);
+						rhsTrackVar.globalClosingState &= ~(SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE|FOREACH_ELEMENT_VAR);
 					}
 				} else {
 					if (rhs instanceof AllocationExpression || rhs instanceof ConditionalExpression) {
@@ -484,7 +486,7 @@
 						}
 					}
 					// re-assigning from a fresh value, mark as not-closed again:
-					if ((previousTracker.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE)) == 0
+					if ((previousTracker.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE|FOREACH_ELEMENT_VAR)) == 0
 							&& flowInfo.hasNullInfoFor(previousTracker.binding)) // avoid spilling info into a branch that doesn't see the corresponding resource
 						flowInfo.markAsDefinitelyNull(previousTracker.binding);
 					local.closeTracker = analyseCloseableExpression(flowInfo, flowContext, local, location, rhs, previousTracker);
@@ -494,7 +496,7 @@
 				if (rhsTrackVar != null) {
 					local.closeTracker = rhsTrackVar;
 					// a fresh resource, mark as not-closed:
-					if ((rhsTrackVar.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE)) == 0)
+					if ((rhsTrackVar.globalClosingState & (SHARED_WITH_OUTSIDE|OWNED_BY_OUTSIDE|FOREACH_ELEMENT_VAR)) == 0)
 						flowInfo.markAsDefinitelyNull(rhsTrackVar.binding);
 // TODO(stephan): this might be useful, but I could not find a test case for it: 
 //					if (flowContext.initsOnFinally != null)
@@ -753,6 +755,12 @@
 		return flowInfo;
 	}
 
+	public static void markForeachElementVar(LocalDeclaration local) {
+		if (local.binding != null && local.binding.closeTracker != null) {
+			local.binding.closeTracker.globalClosingState |= FOREACH_ELEMENT_VAR;
+		}
+	}
+
 	/**
 	 * Iterator for a set of FakedTrackingVariable, which dispenses the elements 
 	 * according to the priorities defined by enum {@link Stage}.
@@ -987,7 +995,7 @@
 	}
 
 	public void reportExplicitClosing(ProblemReporter problemReporter) {
-		if ((this.globalClosingState & (OWNED_BY_OUTSIDE|REPORTED_EXPLICIT_CLOSE)) == 0) { // can't use t-w-r for OWNED_BY_OUTSIDE
+		if ((this.globalClosingState & (OWNED_BY_OUTSIDE|REPORTED_EXPLICIT_CLOSE|FOREACH_ELEMENT_VAR)) == 0) { // can't use t-w-r for OWNED_BY_OUTSIDE
 			this.globalClosingState |= REPORTED_EXPLICIT_CLOSE;
 			problemReporter.explicitlyClosedAutoCloseable(this);
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
index edbc221..fe438b0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
@@ -99,7 +99,7 @@
 		int initialComplaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED;
 
 		// process the element variable and collection
-		flowInfo = this.elementVariable.analyseCode(this.scope, flowContext, flowInfo);		
+		flowInfo = this.elementVariable.analyseCode(this.scope, flowContext, flowInfo);
 		FlowInfo condInfo = this.collection.analyseCode(this.scope, flowContext, flowInfo.copy());
 		this.collection.checkNPE(currentScope, flowContext, condInfo.copy(), 1);
 		LocalVariableBinding elementVarBinding = this.elementVariable.binding;
@@ -131,6 +131,11 @@
 
 			if (this.action.complainIfUnreachable(actionInfo, this.scope, initialComplaintLevel, true) < Statement.COMPLAINED_UNREACHABLE) {
 				actionInfo = this.action.analyseCode(this.scope, loopingContext, actionInfo).unconditionalCopy();
+				if (this.action instanceof Block) {
+					FakedTrackingVariable.markForeachElementVar(this.elementVariable);
+					// action.analyseCode() missed the following check due to identical scopes of ForeachStatement and Block:
+					this.scope.checkUnclosedCloseables(actionInfo, loopingContext, null, null);
+				}
 			}
 
 			// code generation can be optimized when no need to continue in the loop
@@ -147,6 +152,9 @@
 			}
 		} else {
 			exitBranch = condInfo.initsWhenFalse();
+			if (this.action instanceof Block && !this.action.isEmptyBlock()) {
+				this.scope.checkUnclosedCloseables(actionInfo, loopingContext, null, null);
+			}
 		}
 
 		// we need the variable to iterate the collection even if the
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
index 48e4112..422d230 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
@@ -174,10 +174,9 @@
 			case ClassFileConstants.MAJOR_VERSION_1_1:
 				return ((long)ClassFileConstants.MAJOR_VERSION_1_1 << 16) + ClassFileConstants.MINOR_VERSION_3;
 			default:
-				if (major <= MAJOR_LATEST_VERSION)
-					return ((long)major << 16) + ClassFileConstants.MINOR_VERSION_0;
+				major = Math.min(major, MAJOR_LATEST_VERSION);
+				return ((long)major << 16) + ClassFileConstants.MINOR_VERSION_0;
 		}
-		return 0;
 	}
 	/*
 	 * cldc1.1 is 45.3, but we modify it to be different from JDK1_1.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java
index e602d24..b7b81f4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java
@@ -16,6 +16,7 @@
 import java.util.function.Predicate;
 
 import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
+import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray;
 
 /**
  * A module aware name environment
@@ -107,6 +108,18 @@
 	/** Answer a type identified by the given names. moduleName may be one of the special names from ModuleBinding (ANY, ANY_NAMED, UNNAMED). */
 	NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName);
 	char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName);
+	default char[][] getUniqueModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) {
+		char[][] allNames = getModulesDeclaringPackage(parentPackageName, name, moduleName);
+		if (allNames != null && allNames.length > 1) {
+			SimpleSetOfCharArray set = new SimpleSetOfCharArray(allNames.length);
+			for (char[] oneName : allNames)
+				set.add(oneName);
+			allNames = new char[set.elementSize][];
+			set.asArray(allNames);
+		}
+		return allNames;
+	}
+
 	
 	/**
 	 * Answer whether the given package (within the given module) contains any compilation unit.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 08845d0..802ab27 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -831,6 +831,9 @@
 		return 0;
 	}
 	public static long versionToJdkLevel(String versionID) {
+		return versionToJdkLevel(versionID, true);
+	}
+	public static long versionToJdkLevel(String versionID, boolean supportUnreleased) {
 		String version = versionID;
 		// verification is optimized for all versions with same length and same "1." prefix
 		if (version != null && version.length() > 0) {
@@ -866,10 +869,13 @@
 							version = version.substring(0, index);
 					}
 					int major = Integer.parseInt(version) + ClassFileConstants.MAJOR_VERSION_0;
-					if (major <= ClassFileConstants.MAJOR_LATEST_VERSION) {
-						long jdkLevel = ((long) major << 16) + ClassFileConstants.MINOR_VERSION_0;
-						return jdkLevel;
+					if (major > ClassFileConstants.MAJOR_LATEST_VERSION) {
+						if (supportUnreleased)
+							major = ClassFileConstants.MAJOR_LATEST_VERSION;
+						else
+							return 0; // unknown
 					}
+					return ((long) major << 16) + ClassFileConstants.MINOR_VERSION_0;
 				} catch (NumberFormatException e) {
 					// do nothing and return 0 at the end
 				}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
index 6ea3c62..ea2b900 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -125,8 +125,8 @@
 				moduleDecl.createScope(this);
 				moduleDecl.checkAndSetModifiers();
 			}
-		} else if (this.environment.module != this.environment.UnNamedModule) {
-			problemReporter().unnamedPackageInNamedModule(this.environment.module);
+		} else if (module() != this.environment.UnNamedModule) {
+			problemReporter().unnamedPackageInNamedModule(module());
 		}
 	} else {
 		if ((this.fPackage = this.environment.createPackage(this.currentPackageName)) == null) {
@@ -678,6 +678,18 @@
 	return this.captureID++;
 }
 
+@Override
+public ModuleBinding module() {
+	if (!this.referenceContext.isModuleInfo() &&
+			this.referenceContext.types == null &&
+			this.referenceContext.currentPackage == null &&
+			this.referenceContext.imports == null) {
+		this.environment = this.environment.UnNamedModule.environment;
+		return this.environment.UnNamedModule;
+	}
+	return super.module();
+}
+
 /* Answer the problem reporter to use for raising new problems.
 *
 * Note that as a side-effect, this updates the current reference context
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index 90f4431..7c37358 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -300,6 +300,8 @@
 	ReferenceBinding candidate = null;
 	for (NameEnvironmentAnswer answer : answers) {
 		if (answer == null) continue;
+		if (candidate != null && candidate.problemId() == ProblemReasons.Ambiguous)
+			return candidate; // saw enough
 		ModuleBinding answerModule = answer.moduleBinding != null ? answer.moduleBinding : this.UnNamedModule;
 		PackageBinding answerPackage = packageBinding;
 		
@@ -343,8 +345,6 @@
 			continue;
 		}
 		candidate = combine(candidate, answerPackage.getType0(name), clientModule);
-		if (candidate != null && candidate.problemId() == ProblemReasons.Ambiguous)
-			return candidate; // saw enough
 	}
 	return candidate;
 }
@@ -729,7 +729,7 @@
 	if (packageBinding == null || packageBinding == TheNotFoundPackage) {
 		if (this.useModuleSystem) {
 			if (this.module.isUnnamed()) {
-				char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModulesDeclaringPackage(null, constantPoolName[0], ModuleBinding.ANY);
+				char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getUniqueModulesDeclaringPackage(null, constantPoolName[0], ModuleBinding.ANY);
 				if (declaringModules != null) {
 					for (char[] mod : declaringModules) {
 						ModuleBinding declaringModule = this.root.getModule(mod);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java
index 7cf8b0e..d6117ed 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java
@@ -18,9 +18,12 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
@@ -535,12 +538,13 @@
 		}
 
 		PackageBinding binding = null;
+		char[][] declaringModuleNames = null;
 		boolean packageMayBeIncomplete = !considerRequiredModules;
 		if (this.environment.useModuleSystem) {
 			IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment;
-			char[][] declaringModuleNames = moduleEnv.getModulesDeclaringPackage(parentName, name, nameForLookup());
+			declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(parentName, name, nameForLookup());
 			if (declaringModuleNames != null) {
-				if (!this.isUnnamed() && CharOperation.containsEqual(declaringModuleNames, this.moduleName)) {
+				if (CharOperation.containsEqual(declaringModuleNames, this.moduleName)) {
 					// declared here, not yet known, so create it now:
 					binding = new PackageBinding(subPkgCompoundName, parent, this.environment, this);
 				} else if (considerRequiredModules) {
@@ -571,8 +575,8 @@
 		}
 
 		// enrich with split-siblings from visible modules:
-		if (!isUnnamed() && considerRequiredModules) {
-			binding = combineWithPackagesFromRequired(binding, subPkgCompoundName);
+		if (considerRequiredModules) {
+			binding = combineWithPackagesFromOtherRelevantModules(binding, subPkgCompoundName, declaringModuleNames);
 		}
 		if (binding == null || !binding.isValidBinding()) {
 			if (parent != null && !packageMayBeIncomplete) // don't remember package that may still lack some siblings
@@ -596,6 +600,9 @@
 	 * </p>
 	 */
 	public PackageBinding getVisiblePackage(char[][] qualifiedPackageName) {
+		return getVisiblePackage(qualifiedPackageName, true);
+	}
+	PackageBinding getVisiblePackage(char[][] qualifiedPackageName, boolean considerRequiredModules) {
 		if (qualifiedPackageName == null || qualifiedPackageName.length == 0) {
 			return this.environment.defaultPackage;
 		}
@@ -606,7 +613,7 @@
 
 		// check each sub package
 		for (int i = 1; i < qualifiedPackageName.length; i++) {
-			PackageBinding binding = getVisiblePackage(parent, qualifiedPackageName[i], true); 
+			PackageBinding binding = getVisiblePackage(parent, qualifiedPackageName[i], considerRequiredModules); 
 			if (binding == null || binding == LookupEnvironment.TheNotFoundPackage) {
 				return null;
 			}
@@ -653,19 +660,12 @@
 		if (packageBinding.isDeclaredIn(this)) {
 			char[] packageName = packageBinding.readableName();
 			if (checkForSplit && this.environment.useModuleSystem) {
+				char[][] declaringModuleNames = null;
 				if (isUnnamed()) {
 					IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment;
-					char[][] declaringModuleNames = moduleEnv.getModulesDeclaringPackage(null, packageName, ANY);
-					if (declaringModuleNames != null) {
-						for (int i = 0; i < declaringModuleNames.length; i++) {
-							ModuleBinding otherModule = this.environment.getModule(declaringModuleNames[i]);
-							if (otherModule != null && !otherModule.isPackageLookupActive)
-								packageBinding = SplitPackageBinding.combine(otherModule.getVisiblePackage(packageBinding.compoundName), packageBinding, this);
-						}
-					}
-				} else {
-					packageBinding = combineWithPackagesFromRequired(packageBinding, packageBinding.compoundName);
+					declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(null, packageName, ANY);
 				}
+				packageBinding = combineWithPackagesFromOtherRelevantModules(packageBinding, packageBinding.compoundName, declaringModuleNames);
 			}
 			this.declaredPackages.put(packageName, packageBinding);
 			if (packageBinding.parent == null) {
@@ -675,19 +675,40 @@
 		return packageBinding;
 	}
 	
-	private PackageBinding combineWithPackagesFromRequired(PackageBinding currentBinding, char[][] compoundName) {
+	private PackageBinding combineWithPackagesFromOtherRelevantModules(PackageBinding currentBinding, char[][] compoundName, char[][] declaringModuleNames) {
 		boolean save = this.isPackageLookupActive;
 		this.isPackageLookupActive = true;
 		try {
-			for (ModuleBinding moduleBinding : getAllRequiredModules())
-				if (!moduleBinding.isPackageLookupActive)
-					currentBinding = SplitPackageBinding.combine(moduleBinding.getVisiblePackage(compoundName), currentBinding, this);
+			char[] singleName = compoundName[compoundName.length-1];
+			PackageBinding parent = currentBinding != null ? currentBinding.parent : null;
+			for (ModuleBinding moduleBinding : otherRelevantModules(declaringModuleNames)) {
+				if (!moduleBinding.isPackageLookupActive) {
+					PackageBinding nextBinding = parent != null 
+							? moduleBinding.getVisiblePackage(parent, singleName, false)
+							: moduleBinding.getVisiblePackage(compoundName, false);
+					currentBinding = SplitPackageBinding.combine(nextBinding, currentBinding, this);
+				}
+			}
 			return currentBinding;
 		} finally {
 			this.isPackageLookupActive = save;
 		}
 	}
 
+	List<ModuleBinding> otherRelevantModules(char[][] declaringModuleNames) {
+		if (isUnnamed() && declaringModuleNames != null) {
+			// unnamed module reads all named modules,
+			// so all modules declaring the given package are relevant:
+			return Arrays.stream(declaringModuleNames)
+				.filter(modName -> modName != UNNAMED)
+				.map(modName -> this.environment.getModule(modName))
+				.filter(Objects::nonNull)
+				.collect(Collectors.toList());
+		} else {
+			return Arrays.asList(getAllRequiredModules());
+		}
+	}
+
 	/**
 	 * Check if the given package is accessible by this module. True when the package is declared in
 	 * this module or exported by some required module to this module.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index da4f2cf..28ef21f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -751,7 +751,7 @@
 		} while (scope != null);
 		return (CompilationUnitScope) lastScope;
 	}
-	public final ModuleBinding module() {
+	public ModuleBinding module() {
 		return environment().module;
 	}
 	public boolean isLambdaScope() {
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
index 7716e2a..e663811 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
@@ -917,6 +917,7 @@
 	 * @since 3.1
 	 * @deprecated Use {@link #FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_BLOCK_COMMENT} and {@link #FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_JAVADOC_COMMENT}
 	 */
+	@Deprecated
 	public final static String FORMATTER_COMMENT_CLEAR_BLANK_LINES = "org.eclipse.jdt.core.formatter.comment.clear_blank_lines"; //$NON-NLS-1$
 
 	/**
@@ -958,6 +959,7 @@
 	 * @deprecated Use multiple settings for each kind of comments. See {@link #FORMATTER_COMMENT_FORMAT_BLOCK_COMMENT},
 	 * {@link #FORMATTER_COMMENT_FORMAT_JAVADOC_COMMENT} and {@link #FORMATTER_COMMENT_FORMAT_LINE_COMMENT}.
 	 */
+	@Deprecated
 	public final static String FORMATTER_COMMENT_FORMAT = "org.eclipse.jdt.core.formatter.comment.format_comments"; //$NON-NLS-1$
 
 	/**
@@ -1670,6 +1672,7 @@
 	 * {@link #FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_LOCAL_VARIABLE}
 	 * {@link #FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_PARAMETER}
 	 */
+	@Deprecated
 	public static final String FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_after_annotation";//$NON-NLS-1$
 
 	/**
@@ -1689,6 +1692,7 @@
 	 * {@link #FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_PACKAGE}
 	 * {@link #FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_TYPE}
 	 */
+	@Deprecated
 	public static final String FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_MEMBER = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_after_annotation_on_member";//$NON-NLS-1$
 
 	/**
@@ -1902,7 +1906,9 @@
 	 * @see JavaCore#INSERT
 	 * @see JavaCore#DO_NOT_INSERT
 	 * @since 3.2
+	 * @deprecated Use {@link #FORMATTER_KEEP_ANNOTATION_DECLARATION_ON_ONE_LINE} instead.
 	 */
+	@Deprecated
 	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANNOTATION_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_annotation_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
@@ -1914,7 +1920,9 @@
 	 * @see JavaCore#INSERT
 	 * @see JavaCore#DO_NOT_INSERT
 	 * @since 3.0
+	 * @deprecated Use {@link #FORMATTER_KEEP_ANONYMOUS_TYPE_DECLARATION_ON_ONE_LINE} instead.
 	 */
+	@Deprecated
 	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANONYMOUS_TYPE_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_anonymous_type_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
@@ -1926,7 +1934,12 @@
 	 * @see JavaCore#INSERT
 	 * @see JavaCore#DO_NOT_INSERT
 	 * @since 3.0
+	 * @deprecated Use {@link #FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE},
+	 *             {@link #FORMATTER_KEEP_LOOP_BODY_BLOCK_ON_ONE_LINE},
+	 *             {@link #FORMATTER_KEEP_CODE_BLOCK_ON_ONE_LINE}, and
+	 *             {@link #FORMATTER_KEEP_LAMBDA_BODY_BLOCK_ON_ONE_LINE} instead.
 	 */
+	@Deprecated
 	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_block";	//$NON-NLS-1$
 	/**
 	 * <pre>
@@ -1938,7 +1951,9 @@
 	 * @see JavaCore#INSERT
 	 * @see JavaCore#DO_NOT_INSERT
 	 * @since 3.1
+	 * @deprecated Use {@link #FORMATTER_KEEP_ENUM_CONSTANT_DECLARATION_ON_ONE_LINE} instead.
 	 */
+	@Deprecated
 	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_CONSTANT = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_enum_constant";	//$NON-NLS-1$
 	/**
 	 * <pre>
@@ -1950,7 +1965,9 @@
 	 * @see JavaCore#INSERT
 	 * @see JavaCore#DO_NOT_INSERT
 	 * @since 3.1
+	 * @deprecated Use {@link #FORMATTER_KEEP_ENUM_DECLARATION_ON_ONE_LINE} instead.
 	 */
+	@Deprecated
 	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_enum_declaration";	//$NON-NLS-1$
 	/**
 	 * <pre>
@@ -1962,7 +1979,9 @@
 	 * @see JavaCore#INSERT
 	 * @see JavaCore#DO_NOT_INSERT
 	 * @since 3.0
+	 * @deprecated Use {@link #FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE} instead.
 	 */
+	@Deprecated
 	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_method_body";	//$NON-NLS-1$
 	/**
 	 * <pre>
@@ -1974,8 +1993,11 @@
 	 * @see JavaCore#INSERT
 	 * @see JavaCore#DO_NOT_INSERT
 	 * @since 3.0
+	 * @deprecated Use {@link #FORMATTER_KEEP_TYPE_DECLARATION_ON_ONE_LINE} instead.
 	 */
+	@Deprecated
 	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_type_declaration";	//$NON-NLS-1$
+
 	/**
 	 * <pre>
 	 * FORMATTER / Option to insert a space after and in wilcard
@@ -3939,13 +3961,15 @@
 	public static final String FORMATTER_KEEP_EMPTY_ARRAY_INITIALIZER_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_empty_array_initializer_on_one_line"; //$NON-NLS-1$
 	/**
 	 * <pre>
-	 * FORMATTER / Option to keep guardian clause on one line
+	 * FORMATTER / Option to keep guardian clause on one line, in addition to the
+	 *             #FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE option
 	 *     - option id:         "org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line"
 	 *     - possible values:   { TRUE, FALSE }
 	 *     - default:           FALSE
 	 * </pre>
 	 * @see #TRUE
 	 * @see #FALSE
+	 * @see #FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE
 	 * @since 3.0
 	 */
 	public static final String FORMATTER_KEEP_GUARDIAN_CLAUSE_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.format_guardian_clause_on_one_line";	//$NON-NLS-1$
@@ -4013,6 +4037,180 @@
 
 	/**
 	 * <pre>
+	 * FORMATTER / Option to control when a loop body block should be kept on one line
+	 *     - option id:         "org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line"
+	 *     - possible values:   { ONE_LINE_NEVER, ONE_LINE_IF_EMPTY, ONE_LINE_IF_SINGLE_ITEM,
+	 *                            ONE_LINE_ALWAYS, ONE_LINE_PRESERVE }
+	 *     - default:           ONE_LINE_NEVER
+	 * </pre>
+	 * @see #ONE_LINE_NEVER
+	 * @see #ONE_LINE_IF_EMPTY
+	 * @see #ONE_LINE_IF_SINGLE_ITEM
+	 * @see #ONE_LINE_ALWAYS
+	 * @see #ONE_LINE_PRESERVE
+	 * @since 3.16
+	 */
+	public static final String FORMATTER_KEEP_LOOP_BODY_BLOCK_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_loop_body_block_on_one_line"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to control when an if-then statement body block should be kept on one line
+	 *     - option id:         "org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line"
+	 *     - possible values:   { ONE_LINE_NEVER, ONE_LINE_IF_EMPTY, ONE_LINE_IF_SINGLE_ITEM,
+	 *                            ONE_LINE_ALWAYS, ONE_LINE_PRESERVE }
+	 *     - default:           ONE_LINE_NEVER
+	 * </pre>
+	 * @see #ONE_LINE_NEVER
+	 * @see #ONE_LINE_IF_EMPTY
+	 * @see #ONE_LINE_IF_SINGLE_ITEM
+	 * @see #ONE_LINE_ALWAYS
+	 * @see #ONE_LINE_PRESERVE
+	 * @see #FORMATTER_KEEP_GUARDIAN_CLAUSE_ON_ONE_LINE for a special case
+	 * @since 3.16
+	 */
+	public static final String FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_if_then_body_block_on_one_line"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to control when a code block other than if-then and loop body should
+	 *             be kept on one line
+	 *     - option id:         "org.eclipse.jdt.core.formatter.keep_code_block_on_one_line"
+	 *     - possible values:   { ONE_LINE_NEVER, ONE_LINE_IF_EMPTY }
+	 *     - default:           ONE_LINE_NEVER
+	 * </pre>
+	 * @see #ONE_LINE_NEVER
+	 * @see #ONE_LINE_IF_EMPTY
+	 * @since 3.16
+	 */
+	public static final String FORMATTER_KEEP_CODE_BLOCK_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_code_block_on_one_line"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to control when a method body should be kept on one line
+	 *     - option id:         "org.eclipse.jdt.core.formatter.keep_method_body_on_one_line"
+	 *     - possible values:   { ONE_LINE_NEVER, ONE_LINE_IF_EMPTY, ONE_LINE_IF_SINGLE_ITEM,
+	 *                            ONE_LINE_ALWAYS, ONE_LINE_PRESERVE }
+	 *     - default:           ONE_LINE_NEVER
+	 * </pre>
+	 * @see #ONE_LINE_NEVER
+	 * @see #ONE_LINE_IF_EMPTY
+	 * @see #ONE_LINE_IF_SINGLE_ITEM
+	 * @see #ONE_LINE_ALWAYS
+	 * @see #ONE_LINE_PRESERVE
+	 * @since 3.16
+	 */
+	public static final String FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_method_body_on_one_line"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to control when a lambda body should be kept on one line
+	 *     - option id:         "org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line"
+	 *     - possible values:   { ONE_LINE_NEVER, ONE_LINE_IF_EMPTY, ONE_LINE_IF_SINGLE_ITEM,
+	 *                            ONE_LINE_ALWAYS, ONE_LINE_PRESERVE }
+	 *     - default:           ONE_LINE_NEVER
+	 * </pre>
+	 * @see #ONE_LINE_NEVER
+	 * @see #ONE_LINE_IF_EMPTY
+	 * @see #ONE_LINE_IF_SINGLE_ITEM
+	 * @see #ONE_LINE_ALWAYS
+	 * @see #ONE_LINE_PRESERVE
+	 * @since 3.16
+	 */
+	public static final String FORMATTER_KEEP_LAMBDA_BODY_BLOCK_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_lambda_body_block_on_one_line"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to always keep simple getters and setters on one line, in addition to the
+	 *             #FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE option
+	 *     - option id:         "org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line"
+	 *     - possible values:   { TRUE, FALSE }
+	 *     - default:           FALSE
+	 * </pre>
+	 * @see #TRUE
+	 * @see #FALSE
+	 * @see #FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE
+	 * @since 3.16
+	 */
+	public static final String FORMATTER_KEEP_SIMPLE_GETTER_SETTER_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_simple_getter_setter_on_one_line"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to control when a type declaration should be kept on one line
+	 *     - option id:         "org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line"
+	 *     - possible values:   { ONE_LINE_NEVER, ONE_LINE_IF_EMPTY, ONE_LINE_IF_SINGLE_ITEM,
+	 *                            ONE_LINE_ALWAYS, ONE_LINE_PRESERVE }
+	 *     - default:           ONE_LINE_NEVER
+	 * </pre>
+	 * @see #ONE_LINE_NEVER
+	 * @see #ONE_LINE_IF_EMPTY
+	 * @see #ONE_LINE_IF_SINGLE_ITEM
+	 * @see #ONE_LINE_ALWAYS
+	 * @see #ONE_LINE_PRESERVE
+	 * @since 3.16
+	 * @since 3.0
+	 */
+	public static final String FORMATTER_KEEP_TYPE_DECLARATION_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_type_declaration_on_one_line"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to control when an anonymous type declaration should be kept on one line
+	 *     - option id:         "org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line"
+	 *     - possible values:   { ONE_LINE_NEVER, ONE_LINE_IF_EMPTY, ONE_LINE_IF_SINGLE_ITEM,
+	 *                            ONE_LINE_ALWAYS, ONE_LINE_PRESERVE }
+	 *     - default:           ONE_LINE_NEVER
+	 * </pre>
+	 * @see #ONE_LINE_NEVER
+	 * @see #ONE_LINE_IF_EMPTY
+	 * @see #ONE_LINE_IF_SINGLE_ITEM
+	 * @see #ONE_LINE_ALWAYS
+	 * @see #ONE_LINE_PRESERVE
+	 * @since 3.16
+	 */
+	public static final String FORMATTER_KEEP_ANONYMOUS_TYPE_DECLARATION_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_anonymous_type_declaration_on_one_line"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to control when an enum constant declaration body should be kept on one line
+	 *     - option id:         "org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line"
+	 *     - possible values:   { ONE_LINE_NEVER, ONE_LINE_IF_EMPTY, ONE_LINE_IF_SINGLE_ITEM,
+	 *                            ONE_LINE_ALWAYS, ONE_LINE_PRESERVE }
+	 *     - default:           ONE_LINE_NEVER
+	 * </pre>
+	 * @see #ONE_LINE_NEVER
+	 * @see #ONE_LINE_IF_EMPTY
+	 * @see #ONE_LINE_IF_SINGLE_ITEM
+	 * @see #ONE_LINE_ALWAYS
+	 * @see #ONE_LINE_PRESERVE
+	 * @since 3.16
+	 */
+	public static final String FORMATTER_KEEP_ENUM_CONSTANT_DECLARATION_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_enum_constant_declaration_on_one_line"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to control when an enum declaration should be kept on one line
+	 *     - option id:         "org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line"
+	 *     - possible values:   { ONE_LINE_NEVER, ONE_LINE_IF_EMPTY, ONE_LINE_IF_SINGLE_ITEM,
+	 *                            ONE_LINE_ALWAYS, ONE_LINE_PRESERVE }
+	 *     - default:           ONE_LINE_NEVER
+	 * </pre>
+	 * @see #ONE_LINE_NEVER
+	 * @see #ONE_LINE_IF_EMPTY
+	 * @see #ONE_LINE_IF_SINGLE_ITEM
+	 * @see #ONE_LINE_ALWAYS
+	 * @see #ONE_LINE_PRESERVE
+	 * @since 3.16
+	 */
+	public static final String FORMATTER_KEEP_ENUM_DECLARATION_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_enum_declaration_on_one_line"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to control when an annotation declaration should be kept on one line
+	 *     - option id:         "org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line"
+	 *     - possible values:   { ONE_LINE_NEVER, ONE_LINE_IF_EMPTY, ONE_LINE_IF_SINGLE_ITEM,
+	 *                            ONE_LINE_ALWAYS, ONE_LINE_PRESERVE }
+	 *     - default:           ONE_LINE_NEVER
+	 * </pre>
+	 * @see #ONE_LINE_NEVER
+	 * @see #ONE_LINE_IF_EMPTY
+	 * @see #ONE_LINE_IF_SINGLE_ITEM
+	 * @see #ONE_LINE_ALWAYS
+	 * @see #ONE_LINE_PRESERVE
+	 * @since 3.16
+	 */
+	public static final String FORMATTER_KEEP_ANNOTATION_DECLARATION_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_annotation_declaration_on_one_line"; //$NON-NLS-1$
+
+	/**
+	 * <pre>
 	 * FORMATTER / Option to specify the length of the page. Beyond this length, the formatter will try to split the code
 	 *     - option id:         "org.eclipse.jdt.core.formatter.lineSplit"
 	 *     - possible values:   "&lt;n&gt;", where n is zero or a positive integer
@@ -4439,6 +4637,92 @@
 
 	/**
 	 * <pre>
+	 * FORMATTER / Value to never keep braced code on one line.
+	 * </pre>
+	 * @see #FORMATTER_KEEP_LOOP_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_CODE_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_LAMBDA_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_TYPE_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ANONYMOUS_TYPE_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ENUM_CONSTANT_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ENUM_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ANNOTATION_DECLARATION_ON_ONE_LINE
+	 * @since 3.16
+	 */
+	public static final String ONE_LINE_NEVER = "one_line_never";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Value to keep braced code on one line only if it's empty.
+	 * </pre>
+	 * @see #FORMATTER_KEEP_LOOP_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_CODE_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_LAMBDA_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_TYPE_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ANONYMOUS_TYPE_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ENUM_CONSTANT_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ENUM_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ANNOTATION_DECLARATION_ON_ONE_LINE
+	 * @since 3.16
+	 */
+	public static final String ONE_LINE_IF_EMPTY = "one_line_if_empty";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Value to keep braced code on one line if it contains at most a single
+	 *             item.
+	 * </pre>
+	 * @see #FORMATTER_KEEP_LOOP_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_LAMBDA_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_TYPE_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ANONYMOUS_TYPE_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ENUM_CONSTANT_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ENUM_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ANNOTATION_DECLARATION_ON_ONE_LINE
+	 * @since 3.16
+	 */
+	public static final String ONE_LINE_IF_SINGLE_ITEM = "one_line_if_single_item";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Value to always keep braced code on one line, as long as it doesn't
+	 *             exceed the line width limit.
+	 * </pre>
+	 * @see #FORMATTER_KEEP_LOOP_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_LAMBDA_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_TYPE_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ANONYMOUS_TYPE_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ENUM_CONSTANT_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ENUM_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ANNOTATION_DECLARATION_ON_ONE_LINE
+	 * @since 3.16
+	 */
+	public static final String ONE_LINE_ALWAYS = "one_line_always";	//$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Value to keep braced code on one line as long as it doesn't exceed the
+	 *             line width limit and it was already in one line in the original source.
+	 * </pre>
+	 * @see #FORMATTER_KEEP_LOOP_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_LAMBDA_BODY_BLOCK_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_TYPE_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ANONYMOUS_TYPE_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ENUM_CONSTANT_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ENUM_DECLARATION_ON_ONE_LINE
+	 * @see #FORMATTER_KEEP_ANNOTATION_DECLARATION_ON_ONE_LINE
+	 * @since 3.16
+	 */
+	public static final String ONE_LINE_PRESERVE = "one_line_preserve";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
 	 * FORMATTER / Value to set an option to true.
 	 * </pre>
 	 * @since 3.0
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
index 744b097..c222422 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
@@ -414,6 +414,7 @@
 		LineBreaksPreparator breaksPreparator = new LineBreaksPreparator(this.tokenManager, this.workingOptions);
 		this.astRoot.accept(breaksPreparator);
 		breaksPreparator.finishUp();
+		this.astRoot.accept(new OneLineEnforcer(this.tokenManager, this.workingOptions));
 	}
 
 	private void prepareComments() {
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
index b4ae48f..4f8fce8 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
@@ -19,11 +19,14 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.formatter;
 
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.function.Consumer;
 
-import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 /**
@@ -246,13 +249,19 @@
 	public boolean insert_new_line_before_else_in_if_statement;
 	public boolean insert_new_line_before_finally_in_try_statement;
 	public boolean insert_new_line_before_while_in_do_statement;
-	public boolean insert_new_line_in_empty_anonymous_type_declaration;
-	public boolean insert_new_line_in_empty_block;
-	public boolean insert_new_line_in_empty_annotation_declaration;
-	public boolean insert_new_line_in_empty_enum_constant;
-	public boolean insert_new_line_in_empty_enum_declaration;
-	public boolean insert_new_line_in_empty_method_body;
-	public boolean insert_new_line_in_empty_type_declaration;
+
+	public String keep_loop_body_block_on_one_line;
+	public String keep_if_then_body_block_on_one_line;
+	public String keep_code_block_on_one_line;
+	public String keep_lambda_body_block_on_one_line;
+	public String keep_method_body_on_one_line;
+	public String keep_type_declaration_on_one_line;
+	public String keep_anonymous_type_declaration_on_one_line;
+	public String keep_enum_declaration_on_one_line;
+	public String keep_enum_constant_declaration_on_one_line;
+	public String keep_annotation_declaration_on_one_line;
+	public boolean keep_simple_getter_setter_on_one_line;
+
 	public boolean insert_space_after_and_in_type_parameter;
 	public boolean insert_space_after_assignment_operator;
 	public boolean insert_space_after_at_in_annotation;
@@ -443,6 +452,13 @@
 	public int initial_indentation_level;
 	public String line_separator;
 
+	private final static List<String> KEEP_ON_ONE_LINE_VALUES = Arrays.asList(
+			DefaultCodeFormatterConstants.ONE_LINE_NEVER,
+			DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY,
+			DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM,
+			DefaultCodeFormatterConstants.ONE_LINE_ALWAYS,
+			DefaultCodeFormatterConstants.ONE_LINE_PRESERVE);
+
 	private DefaultCodeFormatterOptions() {
 		// cannot be instantiated
 	}
@@ -576,13 +592,17 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_BEFORE_ELSE_IN_IF_STATEMENT, this.insert_new_line_before_else_in_if_statement? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_BEFORE_FINALLY_IN_TRY_STATEMENT, this.insert_new_line_before_finally_in_try_statement? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_BEFORE_WHILE_IN_DO_STATEMENT, this.insert_new_line_before_while_in_do_statement? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
-		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANONYMOUS_TYPE_DECLARATION, this.insert_new_line_in_empty_anonymous_type_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
-		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK, this.insert_new_line_in_empty_block? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
-		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANNOTATION_DECLARATION, this.insert_new_line_in_empty_annotation_declaration ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
-		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_CONSTANT, this.insert_new_line_in_empty_enum_constant? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
-		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_DECLARATION, this.insert_new_line_in_empty_enum_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
-		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY, this.insert_new_line_in_empty_method_body? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
-		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION, this.insert_new_line_in_empty_type_declaration? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_ANNOTATION_DECLARATION_ON_ONE_LINE, this.keep_annotation_declaration_on_one_line);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_ANONYMOUS_TYPE_DECLARATION_ON_ONE_LINE, this.keep_anonymous_type_declaration_on_one_line);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE, this.keep_if_then_body_block_on_one_line);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_LAMBDA_BODY_BLOCK_ON_ONE_LINE, this.keep_lambda_body_block_on_one_line);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_LOOP_BODY_BLOCK_ON_ONE_LINE, this.keep_loop_body_block_on_one_line);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_CODE_BLOCK_ON_ONE_LINE, this.keep_code_block_on_one_line);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_ENUM_CONSTANT_DECLARATION_ON_ONE_LINE, this.keep_enum_constant_declaration_on_one_line);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_ENUM_DECLARATION_ON_ONE_LINE, this.keep_enum_declaration_on_one_line);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE, this.keep_method_body_on_one_line);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_TYPE_DECLARATION_ON_ONE_LINE, this.keep_type_declaration_on_one_line);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_SIMPLE_GETTER_SETTER_ON_ONE_LINE, this.keep_simple_getter_setter_on_one_line? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_LABEL, this.insert_new_line_after_label? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_AND_IN_TYPE_PARAMETER, this.insert_space_after_and_in_type_parameter? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR, this.insert_space_after_assignment_operator? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
@@ -1521,34 +1541,31 @@
 		if (insertNewLineBeforeWhileInDoStatementOption != null) {
 			this.insert_new_line_before_while_in_do_statement = JavaCore.INSERT.equals(insertNewLineBeforeWhileInDoStatementOption);
 		}
-		final Object insertNewLineInEmptyAnonymousTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANONYMOUS_TYPE_DECLARATION);
-		if (insertNewLineInEmptyAnonymousTypeDeclarationOption != null) {
-			this.insert_new_line_in_empty_anonymous_type_declaration = JavaCore.INSERT.equals(insertNewLineInEmptyAnonymousTypeDeclarationOption);
-		}
-		final Object insertNewLineInEmptyBlockOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK);
-		if (insertNewLineInEmptyBlockOption != null) {
-			this.insert_new_line_in_empty_block = JavaCore.INSERT.equals(insertNewLineInEmptyBlockOption);
-		}
-		final Object insertNewLineInEmptyAnnotationDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANNOTATION_DECLARATION);
-		if (insertNewLineInEmptyAnnotationDeclarationOption != null) {
-			this.insert_new_line_in_empty_annotation_declaration = JavaCore.INSERT.equals(insertNewLineInEmptyAnnotationDeclarationOption);
-		}
-		final Object insertNewLineInEmptyEnumConstantOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_CONSTANT);
-		if (insertNewLineInEmptyEnumConstantOption != null) {
-			this.insert_new_line_in_empty_enum_constant = JavaCore.INSERT.equals(insertNewLineInEmptyEnumConstantOption);
-		}
-		final Object insertNewLineInEmptyEnumDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_DECLARATION);
-		if (insertNewLineInEmptyEnumDeclarationOption != null) {
-			this.insert_new_line_in_empty_enum_declaration = JavaCore.INSERT.equals(insertNewLineInEmptyEnumDeclarationOption);
-		}
-		final Object insertNewLineInEmptyMethodBodyOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY);
-		if (insertNewLineInEmptyMethodBodyOption != null) {
-			this.insert_new_line_in_empty_method_body = JavaCore.INSERT.equals(insertNewLineInEmptyMethodBodyOption);
-		}
-		final Object insertNewLineInEmptyTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION);
-		if (insertNewLineInEmptyTypeDeclarationOption != null) {
-			this.insert_new_line_in_empty_type_declaration = JavaCore.INSERT.equals(insertNewLineInEmptyTypeDeclarationOption);
-		}
+		
+		setString(settings, DefaultCodeFormatterConstants.FORMATTER_KEEP_ANNOTATION_DECLARATION_ON_ONE_LINE, KEEP_ON_ONE_LINE_VALUES,
+				v -> this.keep_annotation_declaration_on_one_line = v);
+		setString(settings, DefaultCodeFormatterConstants.FORMATTER_KEEP_ANONYMOUS_TYPE_DECLARATION_ON_ONE_LINE, KEEP_ON_ONE_LINE_VALUES,
+				v -> this.keep_anonymous_type_declaration_on_one_line = v);
+		setString(settings, DefaultCodeFormatterConstants.FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE, KEEP_ON_ONE_LINE_VALUES,
+				v -> this.keep_if_then_body_block_on_one_line = v);
+		setString(settings, DefaultCodeFormatterConstants.FORMATTER_KEEP_LOOP_BODY_BLOCK_ON_ONE_LINE, KEEP_ON_ONE_LINE_VALUES,
+				v -> this.keep_loop_body_block_on_one_line = v);
+		setString(settings, DefaultCodeFormatterConstants.FORMATTER_KEEP_LAMBDA_BODY_BLOCK_ON_ONE_LINE, KEEP_ON_ONE_LINE_VALUES,
+				v -> this.keep_lambda_body_block_on_one_line = v);
+		setString(settings, DefaultCodeFormatterConstants.FORMATTER_KEEP_CODE_BLOCK_ON_ONE_LINE,
+				Arrays.asList(DefaultCodeFormatterConstants.ONE_LINE_NEVER, DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY),
+				v -> this.keep_code_block_on_one_line = v);
+		setString(settings, DefaultCodeFormatterConstants.FORMATTER_KEEP_ENUM_CONSTANT_DECLARATION_ON_ONE_LINE, KEEP_ON_ONE_LINE_VALUES,
+				v -> this.keep_enum_constant_declaration_on_one_line = v);
+		setString(settings, DefaultCodeFormatterConstants.FORMATTER_KEEP_ENUM_DECLARATION_ON_ONE_LINE, KEEP_ON_ONE_LINE_VALUES,
+				v -> this.keep_enum_declaration_on_one_line = v);
+		setString(settings, DefaultCodeFormatterConstants.FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE, KEEP_ON_ONE_LINE_VALUES,
+				v -> this.keep_method_body_on_one_line = v);
+		setString(settings, DefaultCodeFormatterConstants.FORMATTER_KEEP_TYPE_DECLARATION_ON_ONE_LINE, KEEP_ON_ONE_LINE_VALUES,
+				v -> this.keep_type_declaration_on_one_line = v);
+		setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_KEEP_SIMPLE_GETTER_SETTER_ON_ONE_LINE, DefaultCodeFormatterConstants.TRUE,
+				v -> this.keep_simple_getter_setter_on_one_line = v);
+
 		final Object insertNewLineAfterLabelOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_LABEL);
 		if (insertNewLineAfterLabelOption != null) {
 			this.insert_new_line_after_label = JavaCore.INSERT.equals(insertNewLineAfterLabelOption);
@@ -2380,6 +2397,21 @@
 		return defaultValue;
 	}
 
+	private void setString(Map<String, String> settings, String key, List<String> allowedValues, Consumer<String> setter) {
+		Object value = settings.get(key);
+		if (value != null) {
+			if (!allowedValues.contains(value))
+				throw new IllegalArgumentException("Unrecognized value for setting " + key + ": " + value); //$NON-NLS-1$ //$NON-NLS-2$
+			setter.accept((String) value);
+		}
+	}
+
+	private void setBoolean(Map<String, String> settings, String key, String trueValue, Consumer<Boolean> setter) {
+		Object value = settings.get(key);
+		if (value != null)
+			setter.accept(trueValue.equals(value));
+	}
+
 	/**
 	 * This method is used to handle deprecated preferences which might be replaced by
 	 * one or more preferences.
@@ -2476,6 +2508,51 @@
 				this.insert_new_line_after_annotation_on_local_variable = JavaCore.INSERT.equals(insertNewLineAfterAnnotationOnLocalVariableOption);
 			}
 		}
+
+		// insert new line between empty braces -> keep braced code on one line
+		HashMap<Boolean, String> insertToOneLine = new HashMap<>();
+		insertToOneLine.put(true, DefaultCodeFormatterConstants.ONE_LINE_NEVER);
+		insertToOneLine.put(false, DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY);
+		if (settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_ANNOTATION_DECLARATION_ON_ONE_LINE) == null) {
+			setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANNOTATION_DECLARATION, JavaCore.INSERT,
+					v -> this.keep_annotation_declaration_on_one_line = insertToOneLine.get(v));
+		}
+		if (settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_ANONYMOUS_TYPE_DECLARATION_ON_ONE_LINE) == null) {
+			setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANONYMOUS_TYPE_DECLARATION, JavaCore.INSERT,
+					v -> this.keep_anonymous_type_declaration_on_one_line = insertToOneLine.get(v));
+		}
+		if (settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_IF_THEN_BODY_BLOCK_ON_ONE_LINE) == null) {
+			setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK, JavaCore.INSERT,
+					v -> this.keep_if_then_body_block_on_one_line = insertToOneLine.get(v));
+		}
+		if (settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_LOOP_BODY_BLOCK_ON_ONE_LINE) == null) {
+			setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK, JavaCore.INSERT,
+					v -> this.keep_loop_body_block_on_one_line = insertToOneLine.get(v));
+		}
+		if (settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_LAMBDA_BODY_BLOCK_ON_ONE_LINE) == null) {
+			setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK, JavaCore.INSERT,
+					v -> this.keep_lambda_body_block_on_one_line = insertToOneLine.get(v));
+		}
+		if (settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_CODE_BLOCK_ON_ONE_LINE) == null) {
+			setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK, JavaCore.INSERT,
+					v -> this.keep_code_block_on_one_line = insertToOneLine.get(v));
+		}
+		if (settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_ENUM_CONSTANT_DECLARATION_ON_ONE_LINE) == null) {
+			setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_CONSTANT, JavaCore.INSERT,
+					v -> this.keep_enum_constant_declaration_on_one_line = insertToOneLine.get(v));
+		}
+		if (settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_ENUM_DECLARATION_ON_ONE_LINE) == null) {
+			setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_DECLARATION, JavaCore.INSERT,
+					v -> this.keep_enum_declaration_on_one_line = insertToOneLine.get(v));
+		}
+		if (settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE) == null) {
+			setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY, JavaCore.INSERT,
+					v -> this.keep_method_body_on_one_line = insertToOneLine.get(v));
+		}
+		if (settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_TYPE_DECLARATION_ON_ONE_LINE) == null) {
+			setBoolean(settings, DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION, JavaCore.INSERT,
+					v -> this.keep_type_declaration_on_one_line = insertToOneLine.get(v));
+		}
 	}
 
 	public void setDefaultSettings() {
@@ -2596,13 +2673,17 @@
 		this.insert_new_line_before_else_in_if_statement = false;
 		this.insert_new_line_before_finally_in_try_statement = false;
 		this.insert_new_line_before_while_in_do_statement = false;
-		this.insert_new_line_in_empty_anonymous_type_declaration = true;
-		this.insert_new_line_in_empty_block = true;
-		this.insert_new_line_in_empty_annotation_declaration = true;
-		this.insert_new_line_in_empty_enum_constant = true;
-		this.insert_new_line_in_empty_enum_declaration = true;
-		this.insert_new_line_in_empty_method_body = true;
-		this.insert_new_line_in_empty_type_declaration = true;
+		this.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_if_then_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_loop_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_simple_getter_setter_on_one_line = false;
 		this.insert_space_after_and_in_type_parameter = true;
 		this.insert_space_after_assignment_operator = true;
 		this.insert_space_after_at_in_annotation = false;
@@ -2916,13 +2997,16 @@
 		this.insert_new_line_before_else_in_if_statement = false;
 		this.insert_new_line_before_finally_in_try_statement = false;
 		this.insert_new_line_before_while_in_do_statement = false;
-		this.insert_new_line_in_empty_anonymous_type_declaration = true;
-		this.insert_new_line_in_empty_block = true;
-		this.insert_new_line_in_empty_annotation_declaration = true;
-		this.insert_new_line_in_empty_enum_constant = true;
-		this.insert_new_line_in_empty_enum_declaration = true;
-		this.insert_new_line_in_empty_method_body = true;
-		this.insert_new_line_in_empty_type_declaration = true;
+		this.keep_annotation_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_anonymous_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_if_then_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_lambda_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_loop_body_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_code_block_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_enum_constant_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_enum_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
+		this.keep_type_declaration_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_NEVER;
 		this.insert_space_after_and_in_type_parameter = true;
 		this.insert_space_after_assignment_operator = true;
 		this.insert_space_after_at_in_annotation = false;
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
index b0b16b8..9dc434e 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
@@ -150,8 +150,7 @@
 		breakLineBefore(node);
 
 		handleBracedCode(node, node.getName(), this.options.brace_position_for_type_declaration,
-				this.options.indent_body_declarations_compare_to_type_header,
-				this.options.insert_new_line_in_empty_type_declaration);
+				this.options.indent_body_declarations_compare_to_type_header);
 
 		this.declarationModifierVisited = false;
 		return true;
@@ -203,8 +202,7 @@
 	@Override
 	public boolean visit(EnumDeclaration node) {
 		handleBracedCode(node, node.getName(), this.options.brace_position_for_enum_declaration,
-				this.options.indent_body_declarations_compare_to_enum_declaration_header,
-				this.options.insert_new_line_in_empty_enum_declaration);
+				this.options.indent_body_declarations_compare_to_enum_declaration_header);
 		handleBodyDeclarations(node.bodyDeclarations());
 
 		List<EnumConstantDeclaration> enumConstants = node.enumConstants();
@@ -236,8 +234,7 @@
 	@Override
 	public boolean visit(AnnotationTypeDeclaration node) {
 		handleBracedCode(node, node.getName(), this.options.brace_position_for_annotation_type_declaration,
-				this.options.indent_body_declarations_compare_to_annotation_declaration_header,
-				this.options.insert_new_line_in_empty_annotation_declaration);
+				this.options.indent_body_declarations_compare_to_annotation_declaration_header);
 
 		handleBodyDeclarations(node.bodyDeclarations());
 		if (node.getModifiers() == 0)
@@ -251,12 +248,10 @@
 	public boolean visit(AnonymousClassDeclaration node) {
 		if (node.getParent() instanceof EnumConstantDeclaration) {
 			handleBracedCode(node, null, this.options.brace_position_for_enum_constant,
-					this.options.indent_body_declarations_compare_to_enum_constant_header,
-					this.options.insert_new_line_in_empty_enum_constant);
+					this.options.indent_body_declarations_compare_to_enum_constant_header);
 		} else {
 			handleBracedCode(node, null, this.options.brace_position_for_anonymous_type_declaration,
-					this.options.indent_body_declarations_compare_to_type_header,
-					this.options.insert_new_line_in_empty_anonymous_type_declaration);
+					this.options.indent_body_declarations_compare_to_type_header);
 		}
 		handleBodyDeclarations(node.bodyDeclarations());
 		return true;
@@ -276,9 +271,7 @@
 
 		String bracePosition = node.isConstructor() ? this.options.brace_position_for_constructor_declaration
 				: this.options.brace_position_for_method_declaration;
-		handleBracedCode(node.getBody(), null, bracePosition,
-				this.options.indent_statements_compare_to_body,
-				this.options.insert_new_line_in_empty_method_body);
+		handleBracedCode(node.getBody(), null, bracePosition, this.options.indent_statements_compare_to_body);
 		Token openBrace = this.tm.firstTokenIn(node.getBody(), TokenNameLBRACE);
 		if (openBrace.getLineBreaksAfter() > 0) // if not, these are empty braces
 			openBrace.putLineBreaksAfter(this.options.blank_lines_at_beginning_of_method_body + 1);
@@ -287,18 +280,14 @@
 
 	@Override
 	public boolean visit(Block node) {
-		if (this.options.keep_guardian_clause_on_one_line && this.tm.isGuardClause(node))
-			return true;
-
 		List<Statement> statements = node.statements();
 		for (Statement statement : statements) {
 			if (this.options.put_empty_statement_on_new_line || !(statement instanceof EmptyStatement))
 				breakLineBefore(statement);
 		}
-		if (node.getParent().getLength() == 0)
-			return true; // this is a fake block created by parsing in statements mode
-
 		ASTNode parent = node.getParent();
+		if (parent.getLength() == 0)
+			return true; // this is a fake block created by parsing in statements mode
 		if (parent instanceof MethodDeclaration)
 			return true; // braces have been handled in #visit(MethodDeclaration)
 
@@ -312,8 +301,7 @@
 		} else if (parent instanceof LambdaExpression) {
 			bracePosition = this.options.brace_position_for_lambda_body;
 		}
-		handleBracedCode(node, null, bracePosition, this.options.indent_statements_compare_to_block,
-				this.options.insert_new_line_in_empty_block);
+		handleBracedCode(node, null, bracePosition, this.options.indent_statements_compare_to_block);
 
 		return true;
 	}
@@ -321,7 +309,7 @@
 	@Override
 	public boolean visit(SwitchStatement node) {
 		handleBracedCode(node, node.getExpression(), this.options.brace_position_for_switch,
-				this.options.indent_switchstatements_compare_to_switch, true);
+				this.options.indent_switchstatements_compare_to_switch);
 
 		List<Statement> statements = node.statements();
 		if (this.options.indent_switchstatements_compare_to_cases) {
@@ -690,8 +678,7 @@
 		// using settings for type declaration and fields for now, add new settings if necessary
 		breakLineBefore(node);
 		handleBracedCode(node, node.getName(), this.options.brace_position_for_type_declaration,
-				this.options.indent_body_declarations_compare_to_type_header,
-				this.options.insert_new_line_in_empty_type_declaration);
+				this.options.indent_body_declarations_compare_to_type_header);
 
 		List<ModuleDirective> statements = node.moduleStatements();
 		ModuleDirective previous = null;
@@ -711,8 +698,7 @@
 		this.tm.firstTokenIn(node, -1).breakBefore();
 	}
 
-	private void handleBracedCode(ASTNode node, ASTNode nodeBeforeOpenBrace, String bracePosition, boolean indentBody,
-			boolean newLineInEmpty) {
+	private void handleBracedCode(ASTNode node, ASTNode nodeBeforeOpenBrace, String bracePosition, boolean indentBody) {
 		int openBraceIndex = nodeBeforeOpenBrace == null
 				? this.tm.firstIndexIn(node, TokenNameLBRACE)
 				: this.tm.firstIndexAfter(nodeBeforeOpenBrace, TokenNameLBRACE);
@@ -721,18 +707,9 @@
 		Token closeBraceToken = this.tm.get(closeBraceIndex);
 		handleBracePosition(openBraceToken, closeBraceIndex, bracePosition);
 
-		boolean isEmpty = true;
-		for (int i = openBraceIndex + 1; i < closeBraceIndex; i++) {
-			if (!this.tm.get(i).isComment()) {
-				isEmpty = false;
-				break;
-			}
-		}
+		openBraceToken.breakAfter();
+		closeBraceToken.breakBefore();
 
-		if (!isEmpty || newLineInEmpty) {
-			openBraceToken.breakAfter();
-			closeBraceToken.breakBefore();
-		}
 		if (indentBody) {
 			adjustEmptyLineAfter(openBraceIndex, 1);
 			this.tm.get(openBraceIndex + 1).indent();
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/OneLineEnforcer.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/OneLineEnforcer.java
new file mode 100644
index 0000000..9d9763f
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/OneLineEnforcer.java
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2018 Mateusz Matela and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Mateusz Matela <mateusz.matela@gmail.com> - Initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jdt.internal.formatter;
+
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameLBRACE;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameRBRACE;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamewhile;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
+import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
+import org.eclipse.jdt.core.dom.Assignment;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.DoStatement;
+import org.eclipse.jdt.core.dom.EnhancedForStatement;
+import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
+import org.eclipse.jdt.core.dom.EnumDeclaration;
+import org.eclipse.jdt.core.dom.ExpressionStatement;
+import org.eclipse.jdt.core.dom.ForStatement;
+import org.eclipse.jdt.core.dom.IfStatement;
+import org.eclipse.jdt.core.dom.LambdaExpression;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.ModuleDeclaration;
+import org.eclipse.jdt.core.dom.PrimitiveType;
+import org.eclipse.jdt.core.dom.ReturnStatement;
+import org.eclipse.jdt.core.dom.Statement;
+import org.eclipse.jdt.core.dom.ThrowStatement;
+import org.eclipse.jdt.core.dom.Type;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.WhileStatement;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+
+/** Implementation of the "Keep braced code on one line" feature. */
+public class OneLineEnforcer extends ASTVisitor {
+	private final TokenManager tm;
+	private final DefaultCodeFormatterOptions options;
+
+	public OneLineEnforcer(TokenManager tokenManager, DefaultCodeFormatterOptions options) {
+		this.tm = tokenManager;
+		this.options = options;
+	}
+
+	@Override
+	public void endVisit(TypeDeclaration node) {
+		if (node.getParent().getLength() == 0)
+			return; // this is a fake block created by parsing in statements mode
+		tryKeepOnOneLine(node, node.getName(), node.bodyDeclarations(), this.options.keep_type_declaration_on_one_line);
+	}
+
+	@Override
+	public void endVisit(EnumDeclaration node) {
+		List<ASTNode> items = new ArrayList<>();
+		items.addAll(node.bodyDeclarations());
+		items.addAll(node.enumConstants());
+		tryKeepOnOneLine(node, node.getName(), items, this.options.keep_enum_declaration_on_one_line);
+	}
+
+	@Override
+	public void endVisit(AnnotationTypeDeclaration node) {
+		tryKeepOnOneLine(node, node.getName(), node.bodyDeclarations(),
+				this.options.keep_annotation_declaration_on_one_line);
+	}
+
+	@Override
+	public void endVisit(AnonymousClassDeclaration node) {
+		if (node.getParent() instanceof EnumConstantDeclaration) {
+			tryKeepOnOneLine(node, null, node.bodyDeclarations(),
+					this.options.keep_enum_constant_declaration_on_one_line);
+		} else {
+			tryKeepOnOneLine(node, null, node.bodyDeclarations(),
+					this.options.keep_anonymous_type_declaration_on_one_line);
+		}
+	}
+
+	@Override
+	public void endVisit(Block node) {
+		ASTNode parent = node.getParent();
+		List<Statement> statements = node.statements();
+		if (parent.getLength() == 0)
+			return; // this is a fake block created by parsing in statements mode
+		String oneLineOption;
+		if (parent instanceof MethodDeclaration) {
+			oneLineOption = this.options.keep_method_body_on_one_line;
+			if (this.options.keep_simple_getter_setter_on_one_line) {
+				MethodDeclaration method = (MethodDeclaration) parent;
+				String name = method.getName().getIdentifier();
+				Type returnType = method.getReturnType2();
+				boolean returnsVoid = returnType instanceof PrimitiveType
+						&& ((PrimitiveType) returnType).getPrimitiveTypeCode() == PrimitiveType.VOID;
+				boolean isGetter = name.matches("(is|get)\\p{Lu}.*") //$NON-NLS-1$
+						&& !method.isConstructor() && !returnsVoid && method.parameters().isEmpty()
+						&& statements.size() == 1 && statements.get(0) instanceof ReturnStatement;
+				boolean isSetter = name.matches("set\\p{Lu}.*") //$NON-NLS-1$
+						&& !method.isConstructor() && returnsVoid && method.parameters().size() == 1
+						&& statements.size() == 1 && statements.get(0) instanceof ExpressionStatement
+						&& ((ExpressionStatement) statements.get(0)).getExpression() instanceof Assignment;
+				if (isGetter || isSetter)
+					oneLineOption = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+			}
+		} else if (parent instanceof IfStatement && ((IfStatement) parent).getElseStatement() == null) {
+			oneLineOption = this.options.keep_if_then_body_block_on_one_line;
+			if (this.options.keep_guardian_clause_on_one_line) {
+				boolean isGuardian = statements.size() == 1 && (statements.get(0) instanceof ReturnStatement
+						|| statements.get(0) instanceof ThrowStatement);
+				// guard clause cannot start with a comment: https://bugs.eclipse.org/58565
+				int openBraceIndex = this.tm.firstIndexIn(node, TokenNameLBRACE);
+				isGuardian = isGuardian && !this.tm.get(openBraceIndex + 1).isComment();
+				if (isGuardian)
+					oneLineOption = DefaultCodeFormatterConstants.ONE_LINE_ALWAYS;
+			}
+		} else if (parent instanceof LambdaExpression) {
+			oneLineOption = this.options.keep_lambda_body_block_on_one_line;
+		} else if (parent instanceof ForStatement || parent instanceof EnhancedForStatement
+				|| parent instanceof WhileStatement) {
+			oneLineOption = this.options.keep_loop_body_block_on_one_line;
+		} else if (parent instanceof DoStatement) {
+			oneLineOption = this.options.keep_loop_body_block_on_one_line;
+			int openBraceIndex = this.tm.firstIndexIn(node, TokenNameLBRACE);
+			int closeBraceIndex = this.tm.lastIndexIn(node, TokenNameRBRACE);
+			Token whileToken = this.tm.firstTokenAfter(node, TokenNamewhile);
+			int lastIndex = whileToken.getLineBreaksBefore() == 0 ? this.tm.lastIndexIn(parent, -1) : closeBraceIndex;
+			tryKeepOnOneLine(openBraceIndex, closeBraceIndex, lastIndex, statements, oneLineOption);
+			return;
+		} else {
+			oneLineOption = this.options.keep_code_block_on_one_line;
+		}
+		tryKeepOnOneLine(node, null, statements, oneLineOption);
+	}
+
+	@Override
+	public void endVisit(ModuleDeclaration node) {
+		tryKeepOnOneLine(node, node.getName(), node.moduleStatements(), this.options.keep_type_declaration_on_one_line);
+	}
+
+	private void tryKeepOnOneLine(ASTNode node, ASTNode nodeBeforeOpenBrace, List<? extends ASTNode> items,
+			String oneLineOption) {
+		int openBraceIndex = nodeBeforeOpenBrace == null ? this.tm.firstIndexIn(node, TokenNameLBRACE)
+				: this.tm.firstIndexAfter(nodeBeforeOpenBrace, TokenNameLBRACE);
+		int closeBraceIndex = this.tm.lastIndexIn(node, TokenNameRBRACE);
+		tryKeepOnOneLine(openBraceIndex, closeBraceIndex, closeBraceIndex, items, oneLineOption);
+	}
+
+	private void tryKeepOnOneLine(int openBraceIndex, int closeBraceIndex, int lastIndex, List<? extends ASTNode> items,
+			String oneLineOption) {
+		if (DefaultCodeFormatterConstants.ONE_LINE_NEVER.equals(oneLineOption))
+			return;
+		if (DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY.equals(oneLineOption) && !items.isEmpty())
+			return;
+		if (DefaultCodeFormatterConstants.ONE_LINE_IF_SINGLE_ITEM.equals(oneLineOption) && items.size() > 1)
+			return;
+		if (DefaultCodeFormatterConstants.ONE_LINE_PRESERVE.equals(oneLineOption)
+				&& this.tm.countLineBreaksBetween(this.tm.get(openBraceIndex), this.tm.get(lastIndex)) > 0)
+			return;
+
+		Set<Integer> breakIndexes = items.stream().map(n -> this.tm.firstIndexIn(n, -1)).collect(Collectors.toSet());
+		breakIndexes.add(openBraceIndex + 1);
+		breakIndexes.add(closeBraceIndex);
+		Token prev = this.tm.get(openBraceIndex);
+		int startPos = this.tm.getPositionInLine(openBraceIndex);
+		int pos = startPos + this.tm.getLength(prev, startPos);
+		for (int i = openBraceIndex + 1; i <= lastIndex; i++) {
+			Token token = this.tm.get(i);
+			int preexistingBreaks = this.tm.countLineBreaksBetween(prev, token);
+			if (this.options.number_of_empty_lines_to_preserve > 0 && preexistingBreaks > 1)
+				return; // blank line will be preserved
+			boolean isSpace = prev.isSpaceAfter() || token.isSpaceBefore();
+			if (prev.isComment() || token.isComment()) {
+				if (preexistingBreaks > 0)
+					return; // line break around a comment will be preserved
+				char charBefore = this.tm.charAt(token.originalStart - 1);
+				isSpace = isSpace || charBefore == ' ' || charBefore == '\t';
+			}
+			if (prev.getLineBreaksAfter() > 0 || token.getLineBreaksBefore() > 0) {
+				if (!breakIndexes.contains(i))
+					return; // extra line break within an item, can't remove it
+				isSpace = isSpace || !(i == closeBraceIndex && i == openBraceIndex + 1);
+			}
+			if (isSpace)
+				pos++;
+			pos += this.tm.getLength(token, pos);
+			prev = token;
+		}
+		if (!items.isEmpty()) {
+			if (items.get(0).getParent().getParent() instanceof LambdaExpression)
+				pos -= startPos; // lambda body could be put in a wrapped line, so only check its own width
+			if (pos > this.options.page_width)
+				return; // line width limit exceeded
+		}
+
+		for (Integer i : breakIndexes) {
+			prev = this.tm.get(i - 1);
+			prev.clearLineBreaksAfter();
+			Token token = this.tm.get(i);
+			token.clearLineBreaksBefore();
+			if (!items.isEmpty())
+				token.spaceBefore();
+		}
+	}
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
index 5c933ff..96353d1 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
@@ -571,11 +571,6 @@
 		Statement thenStatement = node.getThenStatement();
 		handleTokenBefore(thenStatement, TokenNameRPAREN, this.options.insert_space_before_closing_paren_in_if, false);
 
-		if (thenStatement instanceof Block && this.tm.isGuardClause((Block) thenStatement)) {
-			handleToken(thenStatement, TokenNameLBRACE, false, true);
-			this.tm.lastTokenIn(node, TokenNameRBRACE).spaceBefore();
-		}
-
 		handleLoopBody(thenStatement);
 		handleSemicolon(thenStatement);
 		return true;
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java
index 5783e12..4e42073 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014, 2016 Mateusz Matela and others.
+ * Copyright (c) 2014, 2018 Mateusz Matela and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -15,7 +15,6 @@
 
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_BLOCK;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_JAVADOC;
-import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameLBRACE;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameNotAToken;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameStringLiteral;
 
@@ -27,10 +26,6 @@
 import java.util.regex.Pattern;
 
 import org.eclipse.jdt.core.dom.ASTNode;
-import org.eclipse.jdt.core.dom.Block;
-import org.eclipse.jdt.core.dom.IfStatement;
-import org.eclipse.jdt.core.dom.ReturnStatement;
-import org.eclipse.jdt.core.dom.ThrowStatement;
 import org.eclipse.jdt.internal.formatter.Token.WrapMode;
 import org.eclipse.jdt.internal.formatter.linewrap.CommentWrapExecutor;
 
@@ -177,21 +172,6 @@
 		return this.tokens.iterator();
 	}
 
-	public boolean isGuardClause(Block node) {
-		if (node.statements().size() != 1)
-			return false;
-		ASTNode parent = node.getParent();
-		if (!(parent instanceof IfStatement) || ((IfStatement) parent).getElseStatement() != null)
-			return false;
-		Object statement = node.statements().get(0);
-		if (!(statement instanceof ReturnStatement) && !(statement instanceof ThrowStatement))
-			return false;
-		// guard clause cannot start with a comment
-		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=58565
-		int openBraceIndex = firstIndexIn(node, TokenNameLBRACE);
-		return !get(openBraceIndex + 1).isComment();
-	}
-
 	public int firstIndexIn(ASTNode node, int tokenType) {
 		int index = findIndex(node.getStartPosition(), tokenType, true);
 		assert tokenInside(node, index);
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/Aligner.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/Aligner.java
index f71cf15..011565e 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/Aligner.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/Aligner.java
@@ -93,7 +93,7 @@
 	}
 
 	public void handleAlign(List<BodyDeclaration> bodyDeclarations) {
-		if (!this.options.align_type_members_on_columns)
+		if (!this.options.align_type_members_on_columns || areKeptOnOneLine(bodyDeclarations))
 			return;
 		List<List<FieldDeclaration>> fieldGroups = toAlignGroups(bodyDeclarations,
 				n -> optionalCast(n, FieldDeclaration.class));
@@ -110,12 +110,18 @@
 
 	public void handleAlign(Block block) {
 		List<Statement> statements = block.statements();
+		if (areKeptOnOneLine(statements))
+			return;
 		if (this.options.align_variable_declarations_on_columns)
 			alignDeclarations(statements);
 		if (this.options.align_assignment_statements_on_columns)
 			alignAssignmentStatements(statements);
 	}
 
+	private boolean areKeptOnOneLine(List<? extends ASTNode> nodes) {
+		return nodes.stream().allMatch(n -> this.tm.firstTokenIn(n, -1).getLineBreaksBefore() == 0);
+	}
+
 	private void alignDeclarations(List<Statement> statements) {
 		List<List<VariableDeclarationStatement>> variableGroups = toAlignGroups(statements,
 				n -> optionalCast(n, VariableDeclarationStatement.class));
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
index ca9a2c6..cf7ba63 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
@@ -186,10 +186,10 @@
 	 * temporary values used when calling {@link #handleWrap(int)} to avoid ArrayList initialization and long lists of
 	 * parameters
 	 */
-	private List<Integer> wrapIndexes = new ArrayList<Integer>();
+	private List<Integer> wrapIndexes = new ArrayList<>();
 	/** Indexes for wraps that shouldn't happen but should be indented if cannot be removed */
-	private List<Integer> secondaryWrapIndexes = new ArrayList<Integer>();
-	private List<Float> wrapPenalties = new ArrayList<Float>();
+	private List<Integer> secondaryWrapIndexes = new ArrayList<>();
+	private List<Float> wrapPenalties = new ArrayList<>();
 	private int wrapParentIndex = -1;
 	private int wrapGroupEnd = -1;
 
@@ -773,6 +773,23 @@
 	public boolean visit(LambdaExpression node) {
 		if (node.getBody() instanceof Block) {
 			forceContinuousWrapping(node.getBody(), this.tm.firstIndexIn(node, -1));
+
+			List<Statement> statements = ((Block) node.getBody()).statements();
+			if (!statements.isEmpty()) {
+				int openBraceIndex = this.tm.firstIndexBefore(statements.get(0), TokenNameLBRACE);
+				int closeBraceIndex = this.tm.firstIndexAfter(statements.get(statements.size() - 1), TokenNameRBRACE);
+				boolean areKeptOnOneLine = statements.stream()
+						.allMatch(n -> this.tm.firstTokenIn(n, -1).getLineBreaksBefore() == 0);
+				if (areKeptOnOneLine) {
+					for (Statement statement : statements)
+						this.wrapIndexes.add(this.tm.firstIndexIn(statement, -1));
+					this.wrapParentIndex = openBraceIndex;
+					this.wrapGroupEnd = closeBraceIndex;
+					handleWrap(Alignment.M_ONE_PER_LINE_SPLIT, node);
+					this.tm.get(closeBraceIndex).setWrapPolicy(new WrapPolicy(WrapMode.TOP_PRIORITY, openBraceIndex,
+							closeBraceIndex, 0, this.currentDepth, 1, false, false));
+				}
+			}
 		}
 		if (node.hasParentheses()) {
 			List<VariableDeclaration> parameters = node.parameters();
@@ -1036,6 +1053,8 @@
 		} else if (parentNode instanceof DoStatement) {
 			extraIndent = 0;
 			this.wrapParentIndex = this.tm.firstIndexIn(parentNode, -1); // only if !indoentOnColumn
+		} else if (parentNode instanceof LambdaExpression) {
+			extraIndent = 1;
 		} else if ((wrappingOption & Alignment.M_INDENT_BY_ONE) != 0) {
 			extraIndent = 1;
 		} else if (parentNode instanceof ArrayInitializer) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index df16101..1aad2d2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -3058,6 +3058,21 @@
 	}
 
 	/**
+	 * Returns whether the given version of Java or Java Runtime is supported 
+	 * by the Java Development Toolkit.
+	 * 
+	 * A true indicates that the given version is supported. For e.g., if the argument
+	 * is <code>11.0.1</code> and {@link #getAllVersions()} contains <code>11</code>, 
+	 * the method returns <code>true</code>.
+	 * 
+	 * @return a boolean indicating support for the given version of Java or Java Runtime.
+	 * @since 3.16
+	 */
+	public static boolean isSupportedJavaVersion(String version) {
+		return CompilerOptions.versionToJdkLevel(version, false) > 0;
+	}
+
+	/**
 	 * Configurable option value: {@value}.
 	 * @since 2.0
 	 * @category OptionValue
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
index 6dff56a..c8dbd47 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
@@ -246,7 +246,14 @@
 	// TODO(sxenos): setup the external annotation provider if the IBinaryType came from the index
 	if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
 		JavaProject javaProject = (JavaProject) getAncestor(IJavaElement.JAVA_PROJECT);
-		IClasspathEntry entry = javaProject.getClasspathEntryFor(getPath());
+		IClasspathEntry entry;
+		try {
+			entry = javaProject.getClasspathEntryFor(getPath());
+		} catch (JavaModelException jme) {
+			// Access via cached ClassFile/PF/PFR of a closed project?
+			// Ignore and continue with result undecorated
+			return result;
+		}
 		if (entry != null) {
 			PackageFragment pkg = (PackageFragment) getParent();
 			String entryName = Util.concatWith(pkg.names, getElementName(), '/');