Bug 568987 - [15] record compact constructor - Refactor -> Introduce Factory causes NPE
Change-Id: Ibfff5e094d882b8bc37756bfef9c0b579dd73db6
Signed-off-by: Kalyan Prasad Tatavarthi <kalyan_prasad@in.ibm.com>
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/566943/RecCompConst.java b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/566943/RecCompConst.java
new file mode 100644
index 0000000..7c368ac
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/566943/RecCompConst.java
@@ -0,0 +1,10 @@
+package p;
+
+import java.util.List;
+
+public record RecCompConst(int a, char c, String b) {
+
+ public /*[*/RecCompConst/*]*/ {
+ }
+
+}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/566943/RecCompConst_out.java b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/566943/RecCompConst_out.java
new file mode 100644
index 0000000..e889e93
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/566943/RecCompConst_out.java
@@ -0,0 +1,14 @@
+package p;
+
+import java.util.List;
+
+public record RecCompConst(int a, char c, String b) {
+
+ public static RecCompConst createRecCompConst(int a, char c, String b) {
+ return new RecCompConst(a, c, b);
+ }
+
+ public /*[*/RecCompConst/*]*/ {
+ }
+
+}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/568987/RecCanConst.java b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/568987/RecCanConst.java
new file mode 100644
index 0000000..2c388d4
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/568987/RecCanConst.java
@@ -0,0 +1,10 @@
+package p;
+
+import java.util.List;
+
+public record RecCanConst(int a, char c, String b) {
+
+ public /*[*/RecCanConst/*]*/(int a, char c, String b) {
+ }
+
+}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/568987/RecCanConst_out.java b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/568987/RecCanConst_out.java
new file mode 100644
index 0000000..1615a81
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceFactory/Bugzilla/568987/RecCanConst_out.java
@@ -0,0 +1,14 @@
+package p;
+
+import java.util.List;
+
+public record RecCanConst(int a, char c, String b) {
+
+ public static RecCanConst createRecCanConst(int a, char c, String b) {
+ return new RecCanConst(a, c, b);
+ }
+
+ public /*[*/RecCanConst/*]*/(int a, char c, String b) {
+ }
+
+}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/AllRefactoringTests.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/AllRefactoringTests.java
index 0a227c8..5147eed 100644
--- a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/AllRefactoringTests.java
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/AllRefactoringTests.java
@@ -47,6 +47,7 @@
IntroduceParameterTests.class,
IntroduceParameterTests1d7.class,
IntroduceFactoryTests.class,
+ IntroduceFactoryTests15.class,
//-- structure
ChangeSignatureTests.class,
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceFactoryTests.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceFactoryTests.java
index d7208db..c0e51f3 100644
--- a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceFactoryTests.java
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceFactoryTests.java
@@ -14,42 +14,16 @@
*******************************************************************************/
package org.eclipse.jdt.ui.tests.refactoring;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
import org.junit.Test;
-import org.eclipse.jdt.testplugin.JavaProjectHelper;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.NullProgressMonitor;
-
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.ISourceRange;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.SourceRange;
-
-import org.eclipse.jdt.internal.corext.refactoring.code.IntroduceFactoryRefactoring;
-
import org.eclipse.jdt.ui.tests.refactoring.rules.Java1d6Setup;
/**
* @author rfuhrer@watson.ibm.com
*/
-public class IntroduceFactoryTests extends GenericRefactoringTest {
+public class IntroduceFactoryTests extends IntroduceFactoryTestsBase{
private static final String REFACTORING_PATH= "IntroduceFactory/";
public IntroduceFactoryTests() {
@@ -61,467 +35,6 @@
return REFACTORING_PATH;
}
- /**
- * Produces a test file name based on the name of this JUnit testcase.
- * For input files, trims off the trailing part of the test name that
- * begins with a '_', to get rid of the options part, so that we can
- * have a single (suite of) input file(s) but several outputs dependent
- * on the option settings.
- * @param input true iff the requested file is an input file.
- * @return the name of the test file, with a trailing "_in.java" if an input
- * file and a trailing "_XXX.java" if an output file and the test name/options
- * are "_XXX".
- */
- private String getSimpleTestFileName(boolean input) {
- String testName = getName();
- int usIdx= testName.indexOf('_');
- int endIdx= (usIdx >= 0) ? usIdx : testName.length();
- String fileName = (input ? (testName.substring(4, endIdx) + "_in") : testName.substring(4));
-
- return fileName + ".java";
- }
-
- /**
- * Produces a test file name based on the name of this JUnit testcase,
- * like getSimpleTestFileName(), but also prepends the appropriate version
- * of the resource path (depending on the value of <code>positive</code>).
- * Test files are assumed to be located in the resources directory.
- * @param positive true iff the requested file is for a positive unit test
- * @param input true iff the requested file is an input file
- * @return the test file name
- */
- private String getTestFileName(boolean positive, boolean input) {
- String path= TEST_PATH_PREFIX + getRefactoringPath();
-
- path += (positive ? "positive/": "negative/");
- return path + getSimpleTestFileName(input);
- }
-
- /**
- * Produces a compilation unit from an input source file whose name
- * is based on the testcase name.
- * Test files are assumed to be located in the resources directory.
- * @param pack
- * @param positive
- * @param input
- * @return the ICompilationUnit created from the specified test file
- * @throws Exception
- */
- private ICompilationUnit createCUForSimpleTest(IPackageFragment pack,
- boolean positive, boolean input)
- throws Exception
- {
- String fileName= getTestFileName(positive, input);
- String cuName= getSimpleTestFileName(input);
-
- return createCU(pack, cuName, getFileContents(fileName));
- }
-
- /**
- * Produces a test file name based on the name of this JUnit testcase,
- * like getSimpleTestFileName(), but also prepends the appropriate version
- * of the resource path (depending on the value of <code>positive</code>).
- * Test files are assumed to be located in the resources directory.
- * @param project the project
- * @param pack the package fragment
- * @param fileName the file name
- * @param input true iff the requested file is an input file
- * @return the test file name
- */
- private String getBugTestFileName(IJavaProject project, IPackageFragment pack, String fileName, boolean input) {
- String testName= getName();
- String testNumber= testName.substring("test".length());//$NON-NLS-1$
- String path= TEST_PATH_PREFIX + getRefactoringPath() + "Bugzilla/" + testNumber + "/" +
- (project == null ? "" : project.getElementName() + "/") +
- (pack == getPackageP() ? "" : pack.getElementName() + "/");
-
- return path + fileName + (input ? "" : "_out") + ".java";//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- /**
- * Produces a compilation unit from an input source file whose path
- * is based on the testcase name, but whose basename is supplied by
- * the caller.
- * Test files are assumed to be located in the resources directory.
- * @param project can be null if only 1 project exists in the test workspace
- * @param pack
- * @param baseName
- * @param input
- * @return the ICompilationUnit created from the specified test file
- * @throws Exception
- */
- private ICompilationUnit createCUForBugTestCase(IJavaProject project,
- IPackageFragment pack, String baseName, boolean input)
- throws Exception
- {
- String fileName= getBugTestFileName(project, pack, baseName, input);
- String cuName= baseName + (input ? "" : "_out") + ".java";
-
- return createCU(pack, cuName, getFileContents(fileName));
- }
-
- static final String SELECTION_START_HERALD= "/*[*/";
- static final String SELECTION_END_HERALD= "/*]*/";
-
- /**
- * Finds and returns the selection markers in the given source string,
- * i.e. the first occurrences of <code>SELECTION_START_HERALD</code> and
- * <code>SELECTION_END_HERALD</code>. Fails an assertion if either of these
- * markers is not present in the source string.
- * @param source
- * @return an ISourceRange representing the marked selection
- * @throws Exception
- */
- private ISourceRange findSelectionInSource(String source) throws Exception {
- int begin= source.indexOf(SELECTION_START_HERALD) + SELECTION_START_HERALD.length();
- int end= source.indexOf(SELECTION_END_HERALD);
-
- if (begin < SELECTION_START_HERALD.length())
- fail("No selection start comment in input source file!");
- if (end < 0)
- fail("No selection end comment in input source file!");
-
- return new SourceRange(begin, end-begin);
- }
-
- private void doSingleUnitTest(boolean protectConstructor, ICompilationUnit cu, String outputFileName) throws Exception, JavaModelException, IOException {
- ISourceRange selection= findSelectionInSource(cu.getSource());
- IntroduceFactoryRefactoring ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());
-
- ref.setProtectConstructor(protectConstructor);
-
- RefactoringStatus activationResult= ref.checkInitialConditions(new NullProgressMonitor());
-
- assertTrue("activation was supposed to be successful", activationResult.isOK());
-
- RefactoringStatus checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());
-
- if (!checkInputResult.isOK()) {
- performChange(ref, false);
-
- String newSource = cu.getSource();
-
- System.err.println("!!!Precondition failed for " + getName() + "!!!");
- System.err.println("Compile-time error: " + checkInputResult.toString());
- System.err.println("Offending source:");
- System.err.print(newSource);
- fail("precondition was supposed to pass but was " + checkInputResult.toString());
- }
-
- performChange(ref, false);
-
- String newSource = cu.getSource();
-
- assertEqualLines(getName() + ": ", getFileContents(outputFileName), newSource);
- }
-
- private void doSingleUnitTestWithWarning(boolean protectConstructor, ICompilationUnit cu, String outputFileName) throws Exception, JavaModelException, IOException {
- ISourceRange selection= findSelectionInSource(cu.getSource());
- IntroduceFactoryRefactoring ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());
-
- ref.setProtectConstructor(protectConstructor);
-
- RefactoringStatus activationResult= ref.checkInitialConditions(new NullProgressMonitor());
-
- assertTrue("activation was supposed to be successful", activationResult.isOK());
-
- RefactoringStatus checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());
-
- assertEquals(RefactoringStatus.WARNING, checkInputResult.getSeverity());
- performChange(ref, false);
-
- String newSource= cu.getSource();
-
- assertEqualLines(getName() + ": ", getFileContents(outputFileName), newSource);
- }
-
- /**
- * Tests the IntroduceFactoryRefactoring refactoring on a single input source file
- * whose name is the test name (minus the "test" prefix and any trailing
- * options indicator such as "_FFF"), and compares the transformed code
- * to a source file whose name is the test name (minus the "test" prefix).
- * Test files are assumed to be located in the resources directory.
- * @param protectConstructor true iff IntroduceFactoryRefactoring should make the constructor private
- * @throws Exception
- */
- void singleUnitHelper(boolean protectConstructor)
- throws Exception
- {
- ICompilationUnit cu= createCUForSimpleTest(getPackageP(), true, true);
-
- doSingleUnitTest(protectConstructor, cu, getTestFileName(true, false));
- }
-
- /**
- * Tests the IntroduceFactoryRefactoring refactoring on a single input source file
- * whose name is the test name (minus the "test" prefix and any trailing
- * options indicator such as "_FFF"), and compares the transformed code
- * to a source file whose name is the test name (minus the "test" prefix).
- * Test files are assumed to be located in the resources directory.
- * @param baseFileName the base file name
- * @param protectConstructor true iff IntroduceFactoryRefactoring should make the constructor private
- * @throws Exception
- */
- protected void singleUnitBugHelper(String baseFileName, boolean protectConstructor)
- throws Exception
- {
- ICompilationUnit cu= createCUForBugTestCase(null, getPackageP(), baseFileName, true);
-
- doSingleUnitTest(protectConstructor, cu, getBugTestFileName(null, getPackageP(), baseFileName, false));
- }
-
- protected void singleUnitBugHelperWithWarning(String baseFileName, boolean protectConstructor)
- throws Exception
- {
- ICompilationUnit cu= createCUForBugTestCase(null, getPackageP(), baseFileName, true);
-
- doSingleUnitTestWithWarning(protectConstructor, cu, getBugTestFileName(null, getPackageP(), baseFileName, false));
- }
-
- /**
- * Like singleUnitHelper(), but allows for the specification of the names of
- * the generated factory method, class, and interface, as appropriate.
- * @param factoryMethodName the name to use for the generated factory method
- * @param factoryClassName the name of the factory class
- * @throws Exception
- */
- void namesHelper(String factoryMethodName, String factoryClassName)
- throws Exception
- {
- ICompilationUnit cu= createCUForSimpleTest(getPackageP(), true, true);
- ISourceRange selection= findSelectionInSource(cu.getSource());
- IntroduceFactoryRefactoring ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());
-
- RefactoringStatus activationResult= ref.checkInitialConditions(new NullProgressMonitor());
-
- assertTrue("activation was supposed to be successful", activationResult.isOK());
-
- if (factoryMethodName != null)
- ref.setNewMethodName(factoryMethodName);
- if (factoryClassName != null)
- ref.setFactoryClass(factoryClassName);
-
- RefactoringStatus checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());
-
- assertTrue("precondition was supposed to pass but was " + checkInputResult.toString(), checkInputResult.isOK());
-
- performChange(ref, false);
-
- String newSource = cu.getSource();
-
- assertEqualLines(getName() + ": ", getFileContents(getTestFileName(true, false)), newSource);
- }
-
- /**
- * Creates a compilation unit for a source file with a given base name (plus
- * "_in" suffix) in the given package. The source file is assumed to be
- * located in the test resources directory.<br>
- * Currently only handles positive tests.
- * @param fileName the base name of the source file (minus the "_in" suffix)
- * @param pack an IPackageFragment for the containing package
- * @return the ICompilationUnit for the newly-created unit
- * @throws Exception
- */
- private ICompilationUnit createCUFromFileName(String fileName, IPackageFragment pack) throws Exception {
- String fullName = TEST_PATH_PREFIX + getRefactoringPath() + "positive/" + fileName + "_in.java";
-
- return createCU(pack, fileName + "_in.java", getFileContents(fullName));
- }
-
- private void doMultiUnitTest(ICompilationUnit[] CUs, String testPath, String[] outputFileBaseNames, String factoryClassName) throws Exception, JavaModelException, IOException {
- ISourceRange selection= findSelectionInSource(CUs[0].getSource());
- IntroduceFactoryRefactoring ref= new IntroduceFactoryRefactoring(CUs[0], selection.getOffset(), selection.getLength());
-
- RefactoringStatus activationResult= ref.checkInitialConditions(new NullProgressMonitor());
-
- assertTrue("activation was supposed to be successful", activationResult.isOK());
-
- if (factoryClassName != null)
- ref.setFactoryClass(factoryClassName);
-
- RefactoringStatus checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());
-
- assertTrue("precondition was supposed to pass but was " + checkInputResult.toString(), checkInputResult.isOK());
-
- performChange(ref, false);
-
- String testName= getName();
-
- for (int i = 0; i < CUs.length; i++) {
- int optIdx= testName.indexOf("_");
- String testOptions= (optIdx >= 0) ? testName.substring(optIdx) : "";
- String outFileName= testPath + outputFileBaseNames[i] + testOptions + "_out.java";
- String xformedSrc= CUs[i].getSource();
- String expectedSrc= getFileContents(outFileName);
-
- assertEqualLines(getName() + ": ", expectedSrc, xformedSrc);
- }
- }
-
- /**
- * Tests the IntroduceFactoryRefactoring refactoring on a set of input source files
- * whose names are supplied in the <code>fileBaseNames</code> argument,
- * and compares the transformed code to source files whose names are
- * the input base names plus the options suffix (e.g. "_FFF").
- * Test files are assumed to be located in the resources directory.
- * @param staticFactoryMethod true iff IntroduceFactoryRefactoring should make the factory method static
- * @param inputFileBaseNames an array of input source file base names
- * @throws Exception
- */
- void multiUnitHelper(boolean staticFactoryMethod, String[] inputFileBaseNames)
- throws Exception
- {
- IPackageFragment pkg= getPackageP();
- ICompilationUnit CUs[]= new ICompilationUnit[inputFileBaseNames.length];
-
- for (int i = 0; i < inputFileBaseNames.length; i++)
- CUs[i] = createCUFromFileName(inputFileBaseNames[i], pkg);
-
- String testPath= TEST_PATH_PREFIX + getRefactoringPath() + "positive/";
-
- doMultiUnitTest(CUs, testPath, inputFileBaseNames, null);
- }
-
- /**
- * Tests the IntroduceFactoryRefactoring refactoring on a set of input source files
- * whose names are supplied in the <code>fileBaseNames</code> argument,
- * and compares the transformed code to source files whose names are
- * the input base names plus the options suffix (e.g. "_FFF").
- * Test files are assumed to be located in the resources directory.
- * @param staticFactoryMethod true iff IntroduceFactoryRefactoring should make the factory method static
- * @param inputFileBaseNames an array of input source file base names
- * @param factoryClassName the fully-qualified name of the class to receive the factory method, or null
- * if the factory method is to be placed on the class defining the given constructor
- * @throws Exception
- */
- void multiUnitBugHelper(boolean staticFactoryMethod, String[] inputFileBaseNames, String factoryClassName)
- throws Exception
- {
- ICompilationUnit CUs[]= new ICompilationUnit[inputFileBaseNames.length];
-
- for(int i= 0; i < inputFileBaseNames.length; i++) {
- int pkgEnd= inputFileBaseNames[i].lastIndexOf('/')+1;
- boolean explicitPkg= (pkgEnd > 0);
- IPackageFragment pkg= explicitPkg ? getRoot().createPackageFragment(inputFileBaseNames[i].substring(0, pkgEnd-1), true, new NullProgressMonitor()) : getPackageP();
-
- CUs[i]= createCUForBugTestCase(null, pkg, inputFileBaseNames[i].substring(pkgEnd), true);
- }
-
- String testName= getName();
- String testNumber= testName.substring("test".length());
- String testPath= TEST_PATH_PREFIX + getRefactoringPath() + "Bugzilla/" + testNumber + "/";
-
- doMultiUnitTest(CUs, testPath, inputFileBaseNames, factoryClassName);
- }
-
- void multiProjectBugHelper(String[] inputFileBaseNames, String[] dependencies) throws Exception {
- Map<String, Set<String>> projName2PkgNames= collectProjectPackages(inputFileBaseNames);
- Map<String, IJavaProject> projName2Project= new HashMap<>();
- Map<IJavaProject, IPackageFragmentRoot> proj2PkgRoot= new HashMap<>();
-
- try {
- createProjectPackageStructure(projName2PkgNames, projName2Project, proj2PkgRoot);
-
- ICompilationUnit[] CUs= createCUs(inputFileBaseNames, projName2Project, proj2PkgRoot);
-
- addProjectDependencies(dependencies, projName2Project);
-
- String testName= getName();
- String testNumber= testName.substring("test".length());
- String testPath= TEST_PATH_PREFIX + getRefactoringPath() + "Bugzilla/" + testNumber + "/";
-
- doMultiUnitTest(CUs, testPath, inputFileBaseNames, null);
-
- } finally {
- for (IJavaProject project : proj2PkgRoot.keySet()) {
- if (project.exists()) {
- try {
- project.getProject().delete(true, null);
- } catch (CoreException e) {
- // swallow exception to avoid destroying the original one
- e.printStackTrace();
- }
- }
- }
- }
- }
-
- private ICompilationUnit[] createCUs(String[] inputFileBaseNames, Map<String, IJavaProject> projName2Project, Map<IJavaProject, IPackageFragmentRoot> proj2PkgRoot) throws Exception {
- ICompilationUnit CUs[]= new ICompilationUnit[inputFileBaseNames.length];
-
- for(int i= 0; i < inputFileBaseNames.length; i++) {
- String filePath= inputFileBaseNames[i];
-
- int projEnd= filePath.indexOf('/');
- int pkgEnd= filePath.lastIndexOf('/');
- int fileBegin= pkgEnd+1;
-
- String projName= filePath.substring(0, projEnd);
- String pkgName= filePath.substring(projEnd+1, pkgEnd).replace('/', '.');
-
- IJavaProject project= projName2Project.get(projName);
- IPackageFragmentRoot root= proj2PkgRoot.get(project);
- IPackageFragment pkg= root.getPackageFragment(pkgName);
-
- CUs[i]= createCUForBugTestCase(project, pkg, filePath.substring(fileBegin), true);
- }
- return CUs;
- }
-
- private void addProjectDependencies(String[] dependencies, Map<String, IJavaProject> projName2Project) throws JavaModelException {
- for (String dependency : dependencies) {
- // dependent:provider
- int colonIdx= dependency.indexOf(':');
- String depName= dependency.substring(0, colonIdx);
- String provName= dependency.substring(colonIdx+1);
- IJavaProject depProj= projName2Project.get(depName);
- IJavaProject provProj= projName2Project.get(provName);
- JavaProjectHelper.addRequiredProject(depProj, provProj);
- }
- }
-
- private void createProjectPackageStructure(Map<String, Set<String>> projName2PkgNames, Map<String, IJavaProject> projName2Project, Map<IJavaProject, IPackageFragmentRoot> proj2PkgRoot) throws CoreException, JavaModelException {
- for (Map.Entry<String, Set<String>> entry : projName2PkgNames.entrySet()) {
- String projName = entry.getKey();
- IJavaProject project= JavaProjectHelper.createJavaProject(projName, "bin");
- IPackageFragmentRoot root= JavaProjectHelper.addSourceContainer(project, CONTAINER);
- JavaProjectHelper.addRTJar(project);
- Set<IPackageFragment> pkgs= new HashSet<>();
- projName2Project.put(projName, project);
- proj2PkgRoot.put(project, root);
- for (String pkgName : entry.getValue()) {
- pkgs.add(root.createPackageFragment(pkgName, true, null));
- }
- }
- }
-
- private Map<String, Set<String>> collectProjectPackages(String[] inputFileBaseNames) {
- Map<String, Set<String>> proj2Pkgs= new HashMap<>();
-
- for (String filePath : inputFileBaseNames) {
- int projEnd= filePath.indexOf('/');
- String projName= filePath.substring(0, projEnd);
- String pkgName= filePath.substring(projEnd+1, filePath.lastIndexOf('/'));
-
- Set<String> projPkgs= proj2Pkgs.get(projName);
-
- if (projPkgs == null)
- proj2Pkgs.put(projName, projPkgs= new HashSet<>());
- projPkgs.add(pkgName);
- }
- return proj2Pkgs;
- }
-
- private void failHelper(int expectedStatus) throws Exception {
- ICompilationUnit cu= createCUForSimpleTest(getPackageP(), false, true);
- ISourceRange selection= findSelectionInSource(cu.getSource());
- IntroduceFactoryRefactoring ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());
- RefactoringStatus result= performRefactoring(ref);
-
- assertNotNull("precondition was supposed to fail", result);
- assertEquals("status", expectedStatus, result.getSeverity());
- }
-
//--- TESTS
@Test
public void testStaticContext_FFF() throws Exception {
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceFactoryTests15.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceFactoryTests15.java
new file mode 100644
index 0000000..95c4c2d
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceFactoryTests15.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2020 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.ui.tests.refactoring;
+
+import org.junit.Test;
+
+import org.eclipse.jdt.ui.tests.refactoring.rules.JavaPreviewSetup;
+
+public class IntroduceFactoryTests15 extends IntroduceFactoryTestsBase {
+ private static final String REFACTORING_PATH= "IntroduceFactory/";
+
+ public IntroduceFactoryTests15() {
+ rts= new JavaPreviewSetup();
+ }
+
+ @Override
+ protected String getRefactoringPath() {
+ return REFACTORING_PATH;
+ }
+
+ //--- TESTS
+ @Test
+ public void test568987() throws Exception {
+ singleUnitBugHelper("RecCanConst", false);
+ }
+
+ @Test
+ public void test566943() throws Exception {
+ singleUnitBugHelper("RecCompConst", false);
+ }
+}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceFactoryTestsBase.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceFactoryTestsBase.java
new file mode 100644
index 0000000..c29c13c
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceFactoryTestsBase.java
@@ -0,0 +1,531 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2020 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Samrat Dhillon <samrat.dhillon@gmail.com> - [introduce factory] Introduce Factory on an abstract class adds a statement to create an instance of that class - https://bugs.eclipse.org/bugs/show_bug.cgi?id=395016
+ *******************************************************************************/
+package org.eclipse.jdt.ui.tests.refactoring;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jdt.testplugin.JavaProjectHelper;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.ISourceRange;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.SourceRange;
+
+import org.eclipse.jdt.internal.corext.refactoring.code.IntroduceFactoryRefactoring;
+
+import org.eclipse.jdt.ui.tests.refactoring.rules.Java1d6Setup;
+
+/**
+ * @author rfuhrer@watson.ibm.com
+ */
+public class IntroduceFactoryTestsBase extends GenericRefactoringTest {
+ private static final String REFACTORING_PATH= "IntroduceFactory/";
+
+ public IntroduceFactoryTestsBase() {
+ rts= new Java1d6Setup();
+ }
+
+ @Override
+ protected String getRefactoringPath() {
+ return REFACTORING_PATH;
+ }
+
+ /**
+ * Produces a test file name based on the name of this JUnit testcase.
+ * For input files, trims off the trailing part of the test name that
+ * begins with a '_', to get rid of the options part, so that we can
+ * have a single (suite of) input file(s) but several outputs dependent
+ * on the option settings.
+ * @param input true iff the requested file is an input file.
+ * @return the name of the test file, with a trailing "_in.java" if an input
+ * file and a trailing "_XXX.java" if an output file and the test name/options
+ * are "_XXX".
+ */
+ private String getSimpleTestFileName(boolean input) {
+ String testName = getName();
+ int usIdx= testName.indexOf('_');
+ int endIdx= (usIdx >= 0) ? usIdx : testName.length();
+ String fileName = (input ? (testName.substring(4, endIdx) + "_in") : testName.substring(4));
+
+ return fileName + ".java";
+ }
+
+ /**
+ * Produces a test file name based on the name of this JUnit testcase,
+ * like getSimpleTestFileName(), but also prepends the appropriate version
+ * of the resource path (depending on the value of <code>positive</code>).
+ * Test files are assumed to be located in the resources directory.
+ * @param positive true iff the requested file is for a positive unit test
+ * @param input true iff the requested file is an input file
+ * @return the test file name
+ */
+ private String getTestFileName(boolean positive, boolean input) {
+ String path= TEST_PATH_PREFIX + getRefactoringPath();
+
+ path += (positive ? "positive/": "negative/");
+ return path + getSimpleTestFileName(input);
+ }
+
+ /**
+ * Produces a compilation unit from an input source file whose name
+ * is based on the testcase name.
+ * Test files are assumed to be located in the resources directory.
+ * @param pack
+ * @param positive
+ * @param input
+ * @return the ICompilationUnit created from the specified test file
+ * @throws Exception
+ */
+ @SuppressWarnings("javadoc")
+ private ICompilationUnit createCUForSimpleTest(IPackageFragment pack,
+ boolean positive, boolean input)
+ throws Exception
+ {
+ String fileName= getTestFileName(positive, input);
+ String cuName= getSimpleTestFileName(input);
+
+ return createCU(pack, cuName, getFileContents(fileName));
+ }
+
+ /**
+ * Produces a test file name based on the name of this JUnit testcase,
+ * like getSimpleTestFileName(), but also prepends the appropriate version
+ * of the resource path (depending on the value of <code>positive</code>).
+ * Test files are assumed to be located in the resources directory.
+ * @param project the project
+ * @param pack the package fragment
+ * @param fileName the file name
+ * @param input true iff the requested file is an input file
+ * @return the test file name
+ */
+ private String getBugTestFileName(IJavaProject project, IPackageFragment pack, String fileName, boolean input) {
+ String testName= getName();
+ String testNumber= testName.substring("test".length());//$NON-NLS-1$
+ String path= TEST_PATH_PREFIX + getRefactoringPath() + "Bugzilla/" + testNumber + "/" +
+ (project == null ? "" : project.getElementName() + "/") +
+ (pack == getPackageP() ? "" : pack.getElementName() + "/");
+
+ return path + fileName + (input ? "" : "_out") + ".java";//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ /**
+ * Produces a compilation unit from an input source file whose path
+ * is based on the testcase name, but whose basename is supplied by
+ * the caller.
+ * Test files are assumed to be located in the resources directory.
+ * @param project can be null if only 1 project exists in the test workspace
+ * @param pack
+ * @param baseName
+ * @param input
+ * @return the ICompilationUnit created from the specified test file
+ * @throws Exception
+ */
+ @SuppressWarnings("javadoc")
+ private ICompilationUnit createCUForBugTestCase(IJavaProject project,
+ IPackageFragment pack, String baseName, boolean input)
+ throws Exception
+ {
+ String fileName= getBugTestFileName(project, pack, baseName, input);
+ String cuName= baseName + (input ? "" : "_out") + ".java";
+
+ return createCU(pack, cuName, getFileContents(fileName));
+ }
+
+ static final String SELECTION_START_HERALD= "/*[*/";
+ static final String SELECTION_END_HERALD= "/*]*/";
+
+ /**
+ * Finds and returns the selection markers in the given source string,
+ * i.e. the first occurrences of <code>SELECTION_START_HERALD</code> and
+ * <code>SELECTION_END_HERALD</code>. Fails an assertion if either of these
+ * markers is not present in the source string.
+ * @param source
+ * @return an ISourceRange representing the marked selection
+ * @throws Exception
+ */
+ @SuppressWarnings("javadoc")
+ private ISourceRange findSelectionInSource(String source) throws Exception {
+ int begin= source.indexOf(SELECTION_START_HERALD) + SELECTION_START_HERALD.length();
+ int end= source.indexOf(SELECTION_END_HERALD);
+
+ if (begin < SELECTION_START_HERALD.length())
+ fail("No selection start comment in input source file!");
+ if (end < 0)
+ fail("No selection end comment in input source file!");
+
+ return new SourceRange(begin, end-begin);
+ }
+
+ private void doSingleUnitTest(boolean protectConstructor, ICompilationUnit cu, String outputFileName) throws Exception, JavaModelException, IOException {
+ ISourceRange selection= findSelectionInSource(cu.getSource());
+ IntroduceFactoryRefactoring ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());
+
+ ref.setProtectConstructor(protectConstructor);
+
+ RefactoringStatus activationResult= ref.checkInitialConditions(new NullProgressMonitor());
+
+ assertTrue("activation was supposed to be successful", activationResult.isOK());
+
+ RefactoringStatus checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());
+
+ if (!checkInputResult.isOK()) {
+ performChange(ref, false);
+
+ String newSource = cu.getSource();
+
+ System.err.println("!!!Precondition failed for " + getName() + "!!!");
+ System.err.println("Compile-time error: " + checkInputResult.toString());
+ System.err.println("Offending source:");
+ System.err.print(newSource);
+ fail("precondition was supposed to pass but was " + checkInputResult.toString());
+ }
+
+ performChange(ref, false);
+
+ String newSource = cu.getSource();
+
+ assertEqualLines(getName() + ": ", getFileContents(outputFileName), newSource);
+ }
+
+ private void doSingleUnitTestWithWarning(boolean protectConstructor, ICompilationUnit cu, String outputFileName) throws Exception, JavaModelException, IOException {
+ ISourceRange selection= findSelectionInSource(cu.getSource());
+ IntroduceFactoryRefactoring ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());
+
+ ref.setProtectConstructor(protectConstructor);
+
+ RefactoringStatus activationResult= ref.checkInitialConditions(new NullProgressMonitor());
+
+ assertTrue("activation was supposed to be successful", activationResult.isOK());
+
+ RefactoringStatus checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());
+
+ assertEquals(RefactoringStatus.WARNING, checkInputResult.getSeverity());
+ performChange(ref, false);
+
+ String newSource= cu.getSource();
+
+ assertEqualLines(getName() + ": ", getFileContents(outputFileName), newSource);
+ }
+
+ /**
+ * Tests the IntroduceFactoryRefactoring refactoring on a single input source file
+ * whose name is the test name (minus the "test" prefix and any trailing
+ * options indicator such as "_FFF"), and compares the transformed code
+ * to a source file whose name is the test name (minus the "test" prefix).
+ * Test files are assumed to be located in the resources directory.
+ * @param protectConstructor true iff IntroduceFactoryRefactoring should make the constructor private
+ * @throws Exception
+ */
+ @SuppressWarnings("javadoc")
+ void singleUnitHelper(boolean protectConstructor)
+ throws Exception
+ {
+ ICompilationUnit cu= createCUForSimpleTest(getPackageP(), true, true);
+
+ doSingleUnitTest(protectConstructor, cu, getTestFileName(true, false));
+ }
+
+ /**
+ * Tests the IntroduceFactoryRefactoring refactoring on a single input source file
+ * whose name is the test name (minus the "test" prefix and any trailing
+ * options indicator such as "_FFF"), and compares the transformed code
+ * to a source file whose name is the test name (minus the "test" prefix).
+ * Test files are assumed to be located in the resources directory.
+ * @param baseFileName the base file name
+ * @param protectConstructor true iff IntroduceFactoryRefactoring should make the constructor private
+ * @throws Exception
+ */
+ @SuppressWarnings("javadoc")
+ protected void singleUnitBugHelper(String baseFileName, boolean protectConstructor)
+ throws Exception
+ {
+ ICompilationUnit cu= createCUForBugTestCase(null, getPackageP(), baseFileName, true);
+
+ doSingleUnitTest(protectConstructor, cu, getBugTestFileName(null, getPackageP(), baseFileName, false));
+ }
+
+ protected void singleUnitBugHelperWithWarning(String baseFileName, boolean protectConstructor)
+ throws Exception
+ {
+ ICompilationUnit cu= createCUForBugTestCase(null, getPackageP(), baseFileName, true);
+
+ doSingleUnitTestWithWarning(protectConstructor, cu, getBugTestFileName(null, getPackageP(), baseFileName, false));
+ }
+
+ /**
+ * Like singleUnitHelper(), but allows for the specification of the names of
+ * the generated factory method, class, and interface, as appropriate.
+ * @param factoryMethodName the name to use for the generated factory method
+ * @param factoryClassName the name of the factory class
+ * @throws Exception
+ */
+ @SuppressWarnings("javadoc")
+ void namesHelper(String factoryMethodName, String factoryClassName)
+ throws Exception
+ {
+ ICompilationUnit cu= createCUForSimpleTest(getPackageP(), true, true);
+ ISourceRange selection= findSelectionInSource(cu.getSource());
+ IntroduceFactoryRefactoring ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());
+
+ RefactoringStatus activationResult= ref.checkInitialConditions(new NullProgressMonitor());
+
+ assertTrue("activation was supposed to be successful", activationResult.isOK());
+
+ if (factoryMethodName != null)
+ ref.setNewMethodName(factoryMethodName);
+ if (factoryClassName != null)
+ ref.setFactoryClass(factoryClassName);
+
+ RefactoringStatus checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());
+
+ assertTrue("precondition was supposed to pass but was " + checkInputResult.toString(), checkInputResult.isOK());
+
+ performChange(ref, false);
+
+ String newSource = cu.getSource();
+
+ assertEqualLines(getName() + ": ", getFileContents(getTestFileName(true, false)), newSource);
+ }
+
+ /**
+ * Creates a compilation unit for a source file with a given base name (plus
+ * "_in" suffix) in the given package. The source file is assumed to be
+ * located in the test resources directory.<br>
+ * Currently only handles positive tests.
+ * @param fileName the base name of the source file (minus the "_in" suffix)
+ * @param pack an IPackageFragment for the containing package
+ * @return the ICompilationUnit for the newly-created unit
+ * @throws Exception
+ */
+ @SuppressWarnings("javadoc")
+ private ICompilationUnit createCUFromFileName(String fileName, IPackageFragment pack) throws Exception {
+ String fullName = TEST_PATH_PREFIX + getRefactoringPath() + "positive/" + fileName + "_in.java";
+
+ return createCU(pack, fileName + "_in.java", getFileContents(fullName));
+ }
+
+ private void doMultiUnitTest(ICompilationUnit[] CUs, String testPath, String[] outputFileBaseNames, String factoryClassName) throws Exception, JavaModelException, IOException {
+ ISourceRange selection= findSelectionInSource(CUs[0].getSource());
+ IntroduceFactoryRefactoring ref= new IntroduceFactoryRefactoring(CUs[0], selection.getOffset(), selection.getLength());
+
+ RefactoringStatus activationResult= ref.checkInitialConditions(new NullProgressMonitor());
+
+ assertTrue("activation was supposed to be successful", activationResult.isOK());
+
+ if (factoryClassName != null)
+ ref.setFactoryClass(factoryClassName);
+
+ RefactoringStatus checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());
+
+ assertTrue("precondition was supposed to pass but was " + checkInputResult.toString(), checkInputResult.isOK());
+
+ performChange(ref, false);
+
+ String testName= getName();
+
+ for (int i = 0; i < CUs.length; i++) {
+ int optIdx= testName.indexOf("_");
+ String testOptions= (optIdx >= 0) ? testName.substring(optIdx) : "";
+ String outFileName= testPath + outputFileBaseNames[i] + testOptions + "_out.java";
+ String xformedSrc= CUs[i].getSource();
+ String expectedSrc= getFileContents(outFileName);
+
+ assertEqualLines(getName() + ": ", expectedSrc, xformedSrc);
+ }
+ }
+
+ /**
+ * Tests the IntroduceFactoryRefactoring refactoring on a set of input source files
+ * whose names are supplied in the <code>fileBaseNames</code> argument,
+ * and compares the transformed code to source files whose names are
+ * the input base names plus the options suffix (e.g. "_FFF").
+ * Test files are assumed to be located in the resources directory.
+ * @param staticFactoryMethod true iff IntroduceFactoryRefactoring should make the factory method static
+ * @param inputFileBaseNames an array of input source file base names
+ * @throws Exception
+ */
+ @SuppressWarnings("javadoc")
+ void multiUnitHelper(boolean staticFactoryMethod, String[] inputFileBaseNames)
+ throws Exception
+ {
+ IPackageFragment pkg= getPackageP();
+ ICompilationUnit CUs[]= new ICompilationUnit[inputFileBaseNames.length];
+
+ for (int i = 0; i < inputFileBaseNames.length; i++)
+ CUs[i] = createCUFromFileName(inputFileBaseNames[i], pkg);
+
+ String testPath= TEST_PATH_PREFIX + getRefactoringPath() + "positive/";
+
+ doMultiUnitTest(CUs, testPath, inputFileBaseNames, null);
+ }
+
+ /**
+ * Tests the IntroduceFactoryRefactoring refactoring on a set of input source files
+ * whose names are supplied in the <code>fileBaseNames</code> argument,
+ * and compares the transformed code to source files whose names are
+ * the input base names plus the options suffix (e.g. "_FFF").
+ * Test files are assumed to be located in the resources directory.
+ * @param staticFactoryMethod true iff IntroduceFactoryRefactoring should make the factory method static
+ * @param inputFileBaseNames an array of input source file base names
+ * @param factoryClassName the fully-qualified name of the class to receive the factory method, or null
+ * if the factory method is to be placed on the class defining the given constructor
+ * @throws Exception
+ */
+ @SuppressWarnings("javadoc")
+ void multiUnitBugHelper(boolean staticFactoryMethod, String[] inputFileBaseNames, String factoryClassName)
+ throws Exception
+ {
+ ICompilationUnit CUs[]= new ICompilationUnit[inputFileBaseNames.length];
+
+ for(int i= 0; i < inputFileBaseNames.length; i++) {
+ int pkgEnd= inputFileBaseNames[i].lastIndexOf('/')+1;
+ boolean explicitPkg= (pkgEnd > 0);
+ IPackageFragment pkg= explicitPkg ? getRoot().createPackageFragment(inputFileBaseNames[i].substring(0, pkgEnd-1), true, new NullProgressMonitor()) : getPackageP();
+
+ CUs[i]= createCUForBugTestCase(null, pkg, inputFileBaseNames[i].substring(pkgEnd), true);
+ }
+
+ String testName= getName();
+ String testNumber= testName.substring("test".length());
+ String testPath= TEST_PATH_PREFIX + getRefactoringPath() + "Bugzilla/" + testNumber + "/";
+
+ doMultiUnitTest(CUs, testPath, inputFileBaseNames, factoryClassName);
+ }
+
+ void multiProjectBugHelper(String[] inputFileBaseNames, String[] dependencies) throws Exception {
+ Map<String, Set<String>> projName2PkgNames= collectProjectPackages(inputFileBaseNames);
+ Map<String, IJavaProject> projName2Project= new HashMap<>();
+ Map<IJavaProject, IPackageFragmentRoot> proj2PkgRoot= new HashMap<>();
+
+ try {
+ createProjectPackageStructure(projName2PkgNames, projName2Project, proj2PkgRoot);
+
+ ICompilationUnit[] CUs= createCUs(inputFileBaseNames, projName2Project, proj2PkgRoot);
+
+ addProjectDependencies(dependencies, projName2Project);
+
+ String testName= getName();
+ String testNumber= testName.substring("test".length());
+ String testPath= TEST_PATH_PREFIX + getRefactoringPath() + "Bugzilla/" + testNumber + "/";
+
+ doMultiUnitTest(CUs, testPath, inputFileBaseNames, null);
+
+ } finally {
+ for (IJavaProject project : proj2PkgRoot.keySet()) {
+ if (project.exists()) {
+ try {
+ project.getProject().delete(true, null);
+ } catch (CoreException e) {
+ // swallow exception to avoid destroying the original one
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+ private ICompilationUnit[] createCUs(String[] inputFileBaseNames, Map<String, IJavaProject> projName2Project, Map<IJavaProject, IPackageFragmentRoot> proj2PkgRoot) throws Exception {
+ ICompilationUnit CUs[]= new ICompilationUnit[inputFileBaseNames.length];
+
+ for(int i= 0; i < inputFileBaseNames.length; i++) {
+ String filePath= inputFileBaseNames[i];
+
+ int projEnd= filePath.indexOf('/');
+ int pkgEnd= filePath.lastIndexOf('/');
+ int fileBegin= pkgEnd+1;
+
+ String projName= filePath.substring(0, projEnd);
+ String pkgName= filePath.substring(projEnd+1, pkgEnd).replace('/', '.');
+
+ IJavaProject project= projName2Project.get(projName);
+ IPackageFragmentRoot root= proj2PkgRoot.get(project);
+ IPackageFragment pkg= root.getPackageFragment(pkgName);
+
+ CUs[i]= createCUForBugTestCase(project, pkg, filePath.substring(fileBegin), true);
+ }
+ return CUs;
+ }
+
+ private void addProjectDependencies(String[] dependencies, Map<String, IJavaProject> projName2Project) throws JavaModelException {
+ for (String dependency : dependencies) {
+ // dependent:provider
+ int colonIdx= dependency.indexOf(':');
+ String depName= dependency.substring(0, colonIdx);
+ String provName= dependency.substring(colonIdx+1);
+ IJavaProject depProj= projName2Project.get(depName);
+ IJavaProject provProj= projName2Project.get(provName);
+ JavaProjectHelper.addRequiredProject(depProj, provProj);
+ }
+ }
+
+ private void createProjectPackageStructure(Map<String, Set<String>> projName2PkgNames, Map<String, IJavaProject> projName2Project, Map<IJavaProject, IPackageFragmentRoot> proj2PkgRoot) throws CoreException, JavaModelException {
+ for (Map.Entry<String, Set<String>> entry : projName2PkgNames.entrySet()) {
+ String projName = entry.getKey();
+ IJavaProject project= JavaProjectHelper.createJavaProject(projName, "bin");
+ IPackageFragmentRoot root= JavaProjectHelper.addSourceContainer(project, CONTAINER);
+ JavaProjectHelper.addRTJar(project);
+ Set<IPackageFragment> pkgs= new HashSet<>();
+ projName2Project.put(projName, project);
+ proj2PkgRoot.put(project, root);
+ for (String pkgName : entry.getValue()) {
+ pkgs.add(root.createPackageFragment(pkgName, true, null));
+ }
+ }
+ }
+
+ private Map<String, Set<String>> collectProjectPackages(String[] inputFileBaseNames) {
+ Map<String, Set<String>> proj2Pkgs= new HashMap<>();
+
+ for (String filePath : inputFileBaseNames) {
+ int projEnd= filePath.indexOf('/');
+ String projName= filePath.substring(0, projEnd);
+ String pkgName= filePath.substring(projEnd+1, filePath.lastIndexOf('/'));
+
+ Set<String> projPkgs= proj2Pkgs.get(projName);
+
+ if (projPkgs == null)
+ proj2Pkgs.put(projName, projPkgs= new HashSet<>());
+ projPkgs.add(pkgName);
+ }
+ return proj2Pkgs;
+ }
+
+ protected void failHelper(int expectedStatus) throws Exception {
+ ICompilationUnit cu= createCUForSimpleTest(getPackageP(), false, true);
+ ISourceRange selection= findSelectionInSource(cu.getSource());
+ IntroduceFactoryRefactoring ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());
+ RefactoringStatus result= performRefactoring(ref);
+
+ assertNotNull("precondition was supposed to fail", result);
+ assertEquals("status", expectedStatus, result.getSeverity());
+ }
+}
diff --git a/org.eclipse.jdt.ui/.settings/.api_filters b/org.eclipse.jdt.ui/.settings/.api_filters
index 90c76a9..01b5436 100644
--- a/org.eclipse.jdt.ui/.settings/.api_filters
+++ b/org.eclipse.jdt.ui/.settings/.api_filters
@@ -63,6 +63,20 @@
<message_argument value="isCanonicalConstructor()"/>
</message_arguments>
</filter>
+ <filter comment="This is a Java 15 preview feature" id="640712815">
+ <message_arguments>
+ <message_argument value="IMethodBinding"/>
+ <message_argument value="IntroduceFactoryRefactoring"/>
+ <message_argument value="isCompactConstructor()"/>
+ </message_arguments>
+ </filter>
+ <filter comment="This is a Java 15 preview feature" id="640712815">
+ <message_arguments>
+ <message_argument value="RecordDeclaration"/>
+ <message_argument value="IntroduceFactoryRefactoring"/>
+ <message_argument value="recordComponents()"/>
+ </message_arguments>
+ </filter>
</resource>
<resource path="core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ReplaceInvocationsRefactoring.java" type="org.eclipse.jdt.internal.corext.refactoring.code.ReplaceInvocationsRefactoring">
<filter id="571519004">
diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/IntroduceFactoryRefactoring.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/IntroduceFactoryRefactoring.java
index 979ee68..97c3575 100644
--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/IntroduceFactoryRefactoring.java
+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/IntroduceFactoryRefactoring.java
@@ -66,6 +66,7 @@
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.ParameterizedType;
+import org.eclipse.jdt.core.dom.RecordDeclaration;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
@@ -579,7 +580,13 @@
if (ctorDecl != null) {
List<SingleVariableDeclaration> formalArgs= ctorDecl.parameters();
int i= 0;
-
+ if (formalArgs.size() == 0 && numArgs > 0 && fCtorBinding.isCompactConstructor()) {
+ ASTNode parent= ctorDecl.getParent();
+ if (parent instanceof RecordDeclaration) {
+ RecordDeclaration recDecl= (RecordDeclaration) parent;
+ formalArgs= recDecl.recordComponents();
+ }
+ }
for(Iterator<SingleVariableDeclaration> iter= formalArgs.iterator(); iter.hasNext(); i++) {
SingleVariableDeclaration svd= iter.next();