From 7b12f4c00ae777a937dd1f2e6af8e8c4349db8eb Mon Sep 17 00:00:00 2001 From: Christian Schima Date: Tue, 17 Sep 2024 11:11:30 +0200 Subject: [PATCH] Implementation of #1251 (create multiple types at once). --- .../jdt/internal/ui/dialogs/StatusInfo.java | 10 + .../junit/wizards/NewTestSuiteWizardPage.java | 6 +- .../ui/tests/wizardapi/NewTypeWizardTest.java | 206 +- .../ui/wizards/NewWizardMessages.java | 2 + .../ui/wizards/NewWizardMessages.properties | 4 +- .../jdt/ui/wizards/NewTypeWizardPage.java | 2907 +++++++++-------- 6 files changed, 1774 insertions(+), 1361 deletions(-) diff --git a/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/dialogs/StatusInfo.java b/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/dialogs/StatusInfo.java index bff6963d4f1..565768ae18d 100644 --- a/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/dialogs/StatusInfo.java +++ b/org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/dialogs/StatusInfo.java @@ -96,6 +96,16 @@ public void setError(String errorMessage) { fSeverity= IStatus.ERROR; } + /** + * Sets the status to ERROR and answers this instance. + * @param errorMessage The error message (can be empty, but not null) + * @return This instance + */ + public StatusInfo withError(String errorMessage) { + setError(errorMessage); + return this; + } + /** * Sets the status to WARNING. * @param warningMessage The warning message (can be empty, but not null) diff --git a/org.eclipse.jdt.junit/src/org/eclipse/jdt/junit/wizards/NewTestSuiteWizardPage.java b/org.eclipse.jdt.junit/src/org/eclipse/jdt/junit/wizards/NewTestSuiteWizardPage.java index 64333c631d8..2d344c9fbf9 100644 --- a/org.eclipse.jdt.junit/src/org/eclipse/jdt/junit/wizards/NewTestSuiteWizardPage.java +++ b/org.eclipse.jdt.junit/src/org/eclipse/jdt/junit/wizards/NewTestSuiteWizardPage.java @@ -758,14 +758,16 @@ private void internalSetJUnit4(boolean isJUnit4) { } @Override - protected String constructCUContent(ICompilationUnit cu, String typeContent, String lineDelimiter) throws CoreException { + protected String constructCUContent(String typeName, ICompilationUnit cu, String typeContent, String lineDelimiter) + throws CoreException { + if (isJUnit4()) { typeContent= appendAnnotations(typeContent, lineDelimiter); } else if (isJUnit5()) { typeContent= appendAnnotations5(typeContent, lineDelimiter); } - return super.constructCUContent(cu, typeContent, lineDelimiter); + return super.constructCUContent(typeName, cu, typeContent, lineDelimiter); } private String appendAnnotations(String typeContent, String lineDelimiter) { diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/wizardapi/NewTypeWizardTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/wizardapi/NewTypeWizardTest.java index 8045fba48b6..371fab1cb6a 100644 --- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/wizardapi/NewTypeWizardTest.java +++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/wizardapi/NewTypeWizardTest.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Hashtable; import java.util.List; +import java.util.stream.Stream; import org.junit.After; import org.junit.Before; @@ -145,7 +146,7 @@ public void testCreateClass1() throws Exception { * File */ package test1; - + /** * Type */ @@ -187,9 +188,9 @@ public void testCreateClass2() throws Exception { * File */ package test1; - + import java.util.ArrayList; - + /** * Type */ @@ -241,14 +242,14 @@ public class A { * File */ package test1; - + import pack.A; - + /** * Type */ public class E extends A { - + /** * Overridden */ @@ -303,14 +304,14 @@ public class A { * File */ package test1; - + import pack.A; - + /** * Type */ public class E extends A { - + /** * Constructor */ @@ -318,12 +319,12 @@ public E(String t) { super(t); } /* class body */ - + /** * Method */ public static void main(String[] args) { - + } } """; @@ -370,9 +371,9 @@ public class A { String expected= """ package pack; - + import java.util.ArrayList; - + public class A { /** * Type @@ -380,7 +381,70 @@ public class A { public class E extends ArrayList { /* class body */ } - + + public abstract void foo(T t); + } + """; + + StringAsserts.assertEqualStringIgnoreDelim(actual, expected); + } + + @Test + public void testCreateMultipleInnerClasses1() throws Exception { + + IPackageFragment pack0= fSourceFolder.createPackageFragment("pack", false, null); + String str= """ + package pack; + public class A { + public abstract void foo(T t); + } + """; + ICompilationUnit outer= pack0.createCompilationUnit("A.java", str, false, null); + + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + + NewClassWizardPage wizardPage= new NewClassWizardPage(); + wizardPage.setPackageFragmentRoot(fSourceFolder, true); + wizardPage.setPackageFragment(pack1, true); + wizardPage.setEnclosingTypeSelection(true, true); + wizardPage.setEnclosingType(outer.findPrimaryType(), true); + wizardPage.setTypeName("E;F", true); + + wizardPage.setSuperClass("java.util.ArrayList", true); + + List interfaces= new ArrayList<>(); + wizardPage.setSuperInterfaces(interfaces, true); + + wizardPage.setMethodStubSelection(false, false, true, true); + wizardPage.setAddComments(true, true); + wizardPage.enableCommentControl(true); + + FussyProgressMonitor testMonitor= new FussyProgressMonitor(); + wizardPage.createType(testMonitor); + testMonitor.assertUsedUp(); + + String actual= wizardPage.getCreatedType().getCompilationUnit().getSource(); + + String expected= """ + package pack; + + import java.util.ArrayList; + + public class A { + /** + * Type + */ + public class F extends ArrayList { + /* class body */ + } + + /** + * Type + */ + public class E extends ArrayList { + /* class body */ + } + public abstract void foo(T t); } """; @@ -423,11 +487,11 @@ public void testCreateClassExtraImports1() throws Exception { * File */ package test1; - + import java.io.File; import java.util.List; import java.util.Map; - + /** * Type */ @@ -486,16 +550,16 @@ public static class Inner { * File */ package test1; - + import java.util.Map; - + import pack.A; - + /** * Type */ public class E extends A { - + /** * Overridden */ @@ -526,9 +590,9 @@ public static class Inner { IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); String str1= """ package test1; - + import java.util.Map; - + public class B { } """; @@ -558,18 +622,18 @@ public class B { String expected= """ package test1; - + import java.util.Map; - + import pack.A; - + public class B { - + /** * Type */ public class E extends A { - + /** * Overridden */ @@ -612,9 +676,9 @@ public void testCreateInterface() throws Exception { * File */ package test1; - + import java.util.List; - + /** * Type */ @@ -652,7 +716,7 @@ public void testCreateEnum() throws Exception { * File */ package test1; - + /** * Type */ @@ -690,7 +754,7 @@ public void testCreateAnnotation() throws Exception { * File */ package test1; - + /** * Type */ @@ -811,9 +875,9 @@ public void testAttemptCreateExistingClass() throws Exception IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); String str= """ package test1; - + public class Foo1 { - + } """; ICompilationUnit cu= pack1.createCompilationUnit("Foo1.java", str, false, null); @@ -823,9 +887,9 @@ public class Foo1 { pack1= fSourceFolder.createPackageFragment("test2", false, null); String str1= """ package test2; - + public class Foo3 { - + } """; pack1.createCompilationUnit("Foo3.java", str1, false, null); @@ -849,7 +913,7 @@ public void testAddFinalSuperClassError1() throws Exception { IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); String test= """ package test1; - + public final class A{ } """; @@ -877,6 +941,76 @@ public final class A{ assertTrue(expected.equals(status.getMessage())); } + @Test + public void testCreateMultipleClasses1() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + + NewClassWizardPage wizardPage= new NewClassWizardPage(); + wizardPage.setPackageFragmentRoot(fSourceFolder, true); + wizardPage.setPackageFragment(pack1, true); + wizardPage.setEnclosingTypeSelection(false, true); + wizardPage.setTypeName("E;F", true); + + wizardPage.setSuperClass("", true); + + List interfaces= new ArrayList<>(); + wizardPage.setSuperInterfaces(interfaces, true); + + wizardPage.setMethodStubSelection(false, false, false, true); + wizardPage.setAddComments(true, true); + wizardPage.enableCommentControl(true); + + FussyProgressMonitor testMonitor= new FussyProgressMonitor(); + wizardPage.createType(testMonitor); + testMonitor.assertUsedUp(); + + String actual= wizardPage.getCreatedType().getCompilationUnit().getSource(); + + String expected= """ + /** + * File + */ + package test1; + + /** + * Type + */ + public class E { + /* class body */ + } + """; + + StringAsserts.assertEqualStringIgnoreDelim(actual, expected); + } + + @Test + public void testCreateMultipleClassesDuplicateError1() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + + NewClassWizardPage wizardPage = new NewClassWizardPage(); + wizardPage.setPackageFragmentRoot(fSourceFolder, true); + wizardPage.setPackageFragment(pack1, true); + wizardPage.setEnclosingTypeSelection(false, true); + wizardPage.setTypeName("X", true); // Will be changed below + wizardPage.setSuperClass("", true); + wizardPage.setSuperInterfaces(new ArrayList<>(), true); + wizardPage.setMethodStubSelection(false, false, false, true); + wizardPage.setAddComments(true, true); + wizardPage.enableCommentControl(true); + + // In this error examples the first (single letter) class name is always the duplicate + Stream.of("A;A", "B;C;B", "D;D", "E;E< T >", "F;F", "G; T1; T2; T3; G") + .forEach(names -> { + wizardPage.setTypeName(names, true); + IStatus status = wizardPage.getTypeNameStatus(); + assertNotNull(status); + assertTrue(status.getSeverity() == IStatus.ERROR); + String duplicate = names.substring(0, 1); // See comment above + String expected = Messages.format(NewWizardMessages.NewTypeWizardPage_error_DuplicateName, duplicate); + assertEquals(expected, status.getMessage()); + }); + } + private static ITypeBinding getTypeBinding(ICompilationUnit cu) { CompilationUnit compUnit= ASTResolving.createQuickFixAST(cu, null); ITypeBinding tBinding= null; diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.java index bf72550352e..f69b1852fc9 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.java @@ -157,6 +157,8 @@ private NewWizardMessages() { public static String NewTypeWizardPage_error_InvalidTypeName; public static String NewTypeWizardPage_error_QualifiedName; public static String NewTypeWizardPage_info_FileExtensionNotRequired; + public static String NewTypeWizardPage_info_NamesSeparatedBySemicolon; + public static String NewTypeWizardPage_error_DuplicateName; public static String NewTypeWizardPage_warning_TypeNameDiscouraged; public static String NewTypeWizardPage_error_TypeParameters; public static String NewTypeWizardPage_error_InvalidSuperClassName; diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.properties b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.properties index 0e6ca4c8dba..74dc4273ce3 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.properties +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewWizardMessages.properties @@ -109,7 +109,7 @@ NewTypeWizardPage_error_EnclosingNotInCU=Enclosing type is binary. NewTypeWizardPage_error_EnclosingNotEditable=Enclosing type is not editable. NewTypeWizardPage_warning_EnclosingNotInSourceFolder=Enclosing type is not in specified source folder. -NewTypeWizardPage_typename_label=Na&me: +NewTypeWizardPage_typename_label=Na&me(s): NewTypeWizardPage_superclass_label=&Superclass: NewTypeWizardPage_superclass_button=Brows&e... @@ -139,6 +139,8 @@ NewTypeWizardPage_error_TypeNameExistsDifferentCase=Type with same name but diff NewTypeWizardPage_error_InvalidTypeName=Type name is not valid. {0} NewTypeWizardPage_error_QualifiedName=Type name must not be qualified. NewTypeWizardPage_info_FileExtensionNotRequired=The file extension '.java' will not be part of the type name. +NewTypeWizardPage_info_NamesSeparatedBySemicolon=You can enter multiple names separated by semicolon. +NewTypeWizardPage_error_DuplicateName=Duplicate name. {0} NewTypeWizardPage_warning_TypeNameDiscouraged=Type name is discouraged. {0} NewTypeWizardPage_error_TypeParameters=Type name is not valid. Type parameters are only available if source level is 1.5. diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/NewTypeWizardPage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/NewTypeWizardPage.java index ff190fb2a43..6579587e9c9 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/NewTypeWizardPage.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/NewTypeWizardPage.java @@ -11,7 +11,8 @@ * Contributors: * IBM Corporation - initial API and implementation * John Kaplan, johnkaplantech@gmail.com - 108071 [code templates] template for body of newly created class - * Microsoft Corporation - [templates][content assist] - Extract the UI related code - https://bugs.eclipse.org/549989 + * Microsoft Corporation - [templates][content assist] - Extract the UI related code + * https://bugs.eclipse.org/549989 *******************************************************************************/ package org.eclipse.jdt.ui.wizards; @@ -20,11 +21,14 @@ import java.net.URI; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.eclipse.equinox.bidi.StructuredTextTypeHandlerFactory; @@ -44,7 +48,6 @@ import org.eclipse.swt.widgets.Text; import org.eclipse.core.filesystem.EFS; -import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -58,8 +61,9 @@ import org.eclipse.text.edits.TextEdit; -import org.eclipse.jface.contentassist.SubjectControlContentAssistant; import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.util.BidiUtils; @@ -70,6 +74,7 @@ import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.IWizardContainer; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.ITextSelection; @@ -113,7 +118,6 @@ import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; -import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext; import org.eclipse.jdt.core.formatter.CodeFormatter; import org.eclipse.jdt.core.manipulation.CodeGeneration; import org.eclipse.jdt.core.search.IJavaSearchConstants; @@ -193,23 +197,30 @@ */ public abstract class NewTypeWizardPage extends NewContainerWizardPage { - private static final Pattern NUM_PATTERN= Pattern.compile("[0-9]+$"); //$NON-NLS-1$ - /** - * Class used in stub creation routines to add needed imports to a - * compilation unit. + * Class used in stub creation routines to add needed imports to a compilation unit. */ public static class ImportsManager { + /** AST root. */ private final CompilationUnit fAstRoot; + /** Imports rewrite. */ private final ImportRewrite fImportsRewrite; - /* package */ ImportsManager(CompilationUnit astRoot) { - fAstRoot= astRoot; - fImportsRewrite= StubUtility.createImportRewrite(astRoot, true); + /** + * Constructor with package visibility. + * @param astRoot AST root + */ + ImportsManager(CompilationUnit astRoot) { + fAstRoot = astRoot; + fImportsRewrite = StubUtility.createImportRewrite(astRoot, true); } - /* package */ ICompilationUnit getCompilationUnit() { + /** + * Getter with package visibility. + * @return Compilation unit + */ + ICompilationUnit getCompilationUnit() { return fImportsRewrite.getCompilationUnit(); } @@ -218,8 +229,7 @@ public static class ImportsManager { * If an import already exists or the import would conflict with an import * of an other type with the same simple name, the import is not added. * - * @param qualifiedTypeName The fully qualified name of the type to import - * (dot separated). + * @param qualifiedTypeName The fully qualified name of the type to import (dot separated). * @return Returns the simple type name that can be used in the code or the * fully qualified type name if an import conflict prevented the import. */ @@ -232,16 +242,14 @@ public String addImport(String qualifiedTypeName) { * If an import already exists or the import would conflict with an import * of an other type with the same simple name, the import is not added. * - * @param qualifiedTypeName The fully qualified name of the type to import - * (dot separated). + * @param qualifiedTypeName The fully qualified name of the type to import (dot separated). * @param insertPosition the offset where the import will be used * @return Returns the simple type name that can be used in the code or the * fully qualified type name if an import conflict prevented the import. - * * @since 3.8 */ public String addImport(String qualifiedTypeName, int insertPosition) { - ImportRewriteContext context= new ContextSensitiveImportRewriteContext(fAstRoot, insertPosition, fImportsRewrite); + var context = new ContextSensitiveImportRewriteContext(fAstRoot, insertPosition, fImportsRewrite); return fImportsRewrite.addImport(qualifiedTypeName, context); } @@ -251,7 +259,6 @@ public String addImport(String qualifiedTypeName, int insertPosition) { * of an other type with the same simple name, the import is not added. * * @param typeBinding the binding of the type to import - * * @return Returns the simple type name that can be used in the code or the * fully qualified type name if an import conflict prevented the import. */ @@ -266,14 +273,13 @@ public String addImport(ITypeBinding typeBinding) { * * @param typeBinding the binding of the type to import * @param insertPosition the offset where the import will be used - * * @return Returns the simple type name that can be used in the code or the * fully qualified type name if an import conflict prevented the import. * * @since 3.8 */ public String addImport(ITypeBinding typeBinding, int insertPosition) { - ImportRewriteContext context= new ContextSensitiveImportRewriteContext(fAstRoot, insertPosition, fImportsRewrite); + var context = new ContextSensitiveImportRewriteContext(fAstRoot, insertPosition, fImportsRewrite); return fImportsRewrite.addImport(typeBinding, context); } @@ -284,8 +290,7 @@ public String addImport(ITypeBinding typeBinding, int insertPosition) { * * @param declaringTypeName The qualified name of the static's member declaring type * @param simpleName the simple name of the member; either a field or a method name. - * @param isField true specifies that the member is a field, false if it is a - * method. + * @param isField true specifies that the member is a field, false if it is a method. * @return returns either the simple member name if the import was successful or else the qualified name if * an import conflict prevented the import. * @@ -295,229 +300,430 @@ public String addStaticImport(String declaringTypeName, String simpleName, boole return fImportsRewrite.addStaticImport(declaringTypeName, simpleName, isField); } - /* package */ void create(boolean needsSave, IProgressMonitor monitor) throws CoreException { - TextEdit edit= fImportsRewrite.rewriteImports(monitor); + /** + * Package visibility! Creates and applies the rewrite. + * @param needsSave True if saving required + * @param monitor Progress monitor + * @throws CoreException Exception is thrown if the rewrite fails + */ + void create(boolean needsSave, IProgressMonitor monitor) throws CoreException { + TextEdit edit = fImportsRewrite.rewriteImports(monitor); JavaModelUtil.applyEdit(fImportsRewrite.getCompilationUnit(), edit, needsSave, null); } - /* package */ void removeImport(String qualifiedName) { + /** + * Package visibility! Removes an import. + * @param qualifiedName Qualified name to be removed + */ + void removeImport(String qualifiedName) { fImportsRewrite.removeImport(qualifiedName); } - /* package */ void removeStaticImport(String qualifiedName) { + /** + * Package visibility! Removes a static import. + * @param qualifiedName Qualified name to be removed + */ + void removeStaticImport(String qualifiedName) { fImportsRewrite.removeStaticImport(qualifiedName); } } + /** + * This record represents a type creation result. + * @param createdType Created type + * @param imports Imports manager + * @param existingImports Existing imports + * @param connectedCU Connected compilation unit + * @param needsSave True if saving is required + * @param lineDelimiter Line delimiter + */ + private record TypeCreationResult(IType createdType, ImportsManager imports, Collection existingImports, + ICompilationUnit connectedCU, boolean needsSave, String lineDelimiter) { + } - /** Public access flag. See The Java Virtual Machine Specification for more details. */ - public int F_PUBLIC = Flags.AccPublic; - /** Private access flag. See The Java Virtual Machine Specification for more details. */ - public int F_PRIVATE = Flags.AccPrivate; - /** Protected access flag. See The Java Virtual Machine Specification for more details. */ - public int F_PROTECTED = Flags.AccProtected; - /** Static access flag. See The Java Virtual Machine Specification for more details. */ - public int F_STATIC = Flags.AccStatic; - /** Final access flag. See The Java Virtual Machine Specification for more details. */ - public int F_FINAL = Flags.AccFinal; - /** Abstract property flag. See The Java Virtual Machine Specification for more details. */ - public int F_ABSTRACT = Flags.AccAbstract; - /** Non-Sealed access Flag. */ - private int F_NON_SEALED = Flags.AccNonSealed; - /** Sealed access Flag. */ - private int F_SEALED = Flags.AccSealed; - - private final static String PAGE_NAME= "NewTypeWizardPage"; //$NON-NLS-1$ - - /** Field ID of the package input field. */ - protected final static String PACKAGE= PAGE_NAME + ".package"; //$NON-NLS-1$ - /** Field ID of the enclosing type input field. */ - protected final static String ENCLOSING= PAGE_NAME + ".enclosing"; //$NON-NLS-1$ - /** Field ID of the enclosing type checkbox. */ - protected final static String ENCLOSINGSELECTION= ENCLOSING + ".selection"; //$NON-NLS-1$ - /** Field ID of the type name input field. */ - protected final static String TYPENAME= PAGE_NAME + ".typename"; //$NON-NLS-1$ - /** Field ID of the super type input field. */ - protected final static String SUPER= PAGE_NAME + ".superclass"; //$NON-NLS-1$ - /** Field ID of the super interfaces input field. */ - protected final static String INTERFACES= PAGE_NAME + ".interfaces"; //$NON-NLS-1$ - /** Field ID of the modifier check boxes. */ - protected final static String MODIFIERS= PAGE_NAME + ".modifiers"; //$NON-NLS-1$ - /** Field ID of the modifier check boxes. - * @since 3.25*/ - protected final static String SEALEDMODIFIERS= PAGE_NAME + ".sealedmodifiers"; //$NON-NLS-1$ - /** Field ID of the method stubs check boxes. */ - protected final static String METHODS= PAGE_NAME + ".methods"; //$NON-NLS-1$ + /** + * This record represents type name variants (with and without type parameters). + * @param nameWithParams Type name with type parameters + * @param nameWithoutParams Type name without type parameters + * @param duplicate Flag indicating a duplicate + */ + private record TypeNameVariants(String nameWithParams, String nameWithoutParams, boolean duplicate) { + } + /** + * This class represents an interface wrapper. + */ private static class InterfaceWrapper { + /** Interface name. */ private String interfaceName; + /** The type. */ private IType type; + /** + * Constructor. + * @param interfaceName Interface name + */ public InterfaceWrapper(String interfaceName) { this(interfaceName, null); } + /** + * Constructor. + * @param interfaceName Interface name + * @param type The type + */ public InterfaceWrapper(String interfaceName, IType type) { - this.interfaceName= interfaceName; - this.type= type; + this.interfaceName = interfaceName; + this.type = type; } + /** + * {@inheritDoc} + * @see java.lang.Object#hashCode() + */ @Override public int hashCode() { - int hashCode= interfaceName.hashCode(); + int hashCode = interfaceName.hashCode(); if (type != null) { hashCode &= type.hashCode(); } return hashCode; } + /** + * {@inheritDoc} + * @see java.lang.Object#equals(java.lang.Object) + */ @Override public boolean equals(Object obj) { - return obj != null && getClass().equals(obj.getClass()) && ((InterfaceWrapper) obj).interfaceName.equals(interfaceName) && ((InterfaceWrapper) obj).type == type ; + return obj != null && getClass().equals(obj.getClass()) + && ((InterfaceWrapper) obj).interfaceName.equals(interfaceName) + && ((InterfaceWrapper) obj).type == type; } + /** + * Sets the interface name and the type. + * @param newName Interface name + * @param type The type + */ public void setInterfaceName(String newName, IType type) { - this.type= type; - this.interfaceName= newName; + this.type = type; + this.interfaceName = newName; } + /** + * Getter. + * @return The interface name + */ public String getInterfaceName() { return this.interfaceName; } + /** + * Getter. + * @return The type + */ public IType getType() { return this.type; } } + /** + * This class represents an interfaces list label provider. + */ private static class InterfacesListLabelProvider extends LabelProvider { + /** Interface image. */ private Image fInterfaceImage; + /** + * Constructor. + */ public InterfacesListLabelProvider() { - fInterfaceImage= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_INTERFACE); + fInterfaceImage = JavaPluginImages.get(JavaPluginImages.IMG_OBJS_INTERFACE); } + /** + * {@inheritDoc} + * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + */ @Override public String getText(Object element) { return BasicElementLabels.getJavaElementName(((InterfaceWrapper) element).getInterfaceName()); } + /** + * {@inheritDoc} + * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object) + */ @Override public Image getImage(Object element) { return fInterfaceImage; } } - private StringButtonStatusDialogField fPackageDialogField; + // -------- TypeFieldsAdapter -------- + + /** + * This class represents a type fields adapter. + */ + private class TypeFieldsAdapter implements IStringButtonAdapter, IDialogFieldListener, + IListAdapter, SelectionListener { + // -------- IStringButtonAdapter + /** + * {@inheritDoc} + * @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter#changeControlPressed( + * org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField) + */ + @Override + public void changeControlPressed(DialogField field) { + typePageChangeControlPressed(field); + } + + // -------- IListAdapter + /** + * {@inheritDoc} + * @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter#customButtonPressed( + * org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField, int) + */ + @Override + public void customButtonPressed(ListDialogField field, int index) { + typePageCustomButtonPressed(field, index); + } + + /** + * {@inheritDoc} + * @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter#selectionChanged( + * org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField) + */ + @Override + public void selectionChanged(ListDialogField field) { + // Do nothing + } + + // -------- IDialogFieldListener + /** + * {@inheritDoc} + * @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener#dialogFieldChanged( + * org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField) + */ + @Override + public void dialogFieldChanged(DialogField field) { + typePageDialogFieldChanged(field); + } + + /** + * {@inheritDoc} + * @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter#doubleClicked( + * org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField) + */ + @Override + public void doubleClicked(ListDialogField field) { + } + + /** + * {@inheritDoc} + * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) + */ + @Override + public void widgetSelected(SelectionEvent e) { + typePageLinkActivated(); + } + + /** + * {@inheritDoc} + * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent) + */ + @Override + public void widgetDefaultSelected(SelectionEvent e) { + typePageLinkActivated(); + } + } + + /** NUM_PATTERN. */ + private static final Pattern NUM_PATTERN = Pattern.compile("[0-9]+$"); //$NON-NLS-1$ + /** MIN_ONE_LETTER_PATTERN. */ + private static final Pattern MIN_ONE_LETTER_PATTERN = Pattern.compile(".*[a-zA-Z]+.*"); //$NON-NLS-1$ + /** PAGE_NAME. */ + private static final String PAGE_NAME = "NewTypeWizardPage"; //$NON-NLS-1$ + /** Field ID of the package input field. */ + protected static final String PACKAGE = PAGE_NAME + ".package"; //$NON-NLS-1$ + /** Field ID of the enclosing type input field. */ + protected static final String ENCLOSING = PAGE_NAME + ".enclosing"; //$NON-NLS-1$ + /** Field ID of the enclosing type checkbox. */ + protected static final String ENCLOSINGSELECTION = ENCLOSING + ".selection"; //$NON-NLS-1$ + /** Field ID of the type name input field. */ + protected static final String TYPENAME = PAGE_NAME + ".typename"; //$NON-NLS-1$ + /** Field ID of the super type input field. */ + protected static final String SUPER = PAGE_NAME + ".superclass"; //$NON-NLS-1$ + /** Field ID of the super interfaces input field. */ + protected static final String INTERFACES = PAGE_NAME + ".interfaces"; //$NON-NLS-1$ + /** Field ID of the modifier check boxes. */ + protected static final String MODIFIERS = PAGE_NAME + ".modifiers"; //$NON-NLS-1$ + /** Field ID of the modifier check boxes. @since 3.25*/ + protected static final String SEALEDMODIFIERS = PAGE_NAME + ".sealedmodifiers"; //$NON-NLS-1$ + /** Field ID of the method stubs check boxes. */ + protected static final String METHODS = PAGE_NAME + ".methods"; //$NON-NLS-1$ + /** PUBLIC_INDEX. */ + private static final int PUBLIC_INDEX = 0; + /** DEFAULT_INDEX. */ + private static final int DEFAULT_INDEX = 1; + /** PRIVATE_INDEX. */ + private static final int PRIVATE_INDEX = 2; + /** PROTECTED_INDEX. */ + private static final int PROTECTED_INDEX = 3; + /** ABSTRACT_INDEX. */ + private static final int ABSTRACT_INDEX = 0; + /** FINAL_INDEX. */ + private static final int FINAL_INDEX = 1; + /** STATIC_INDEX. */ + private static final int STATIC_INDEX = 2; + /** ENUM_ANNOT_STATIC_INDEX. */ + private static final int ENUM_ANNOT_STATIC_INDEX = 1; + /** SEALED_FINAL_INDEX. */ + private static final int SEALED_FINAL_INDEX = 3; + /** SEALED_INDEX. */ + private static final int SEALED_INDEX = 1; + /** NON_SEALED_INDEX. */ + private static final int NON_SEALED_INDEX = 2; + + /** + * Constant to signal that the created type is a class. + * @since 3.1 + */ + public static final int CLASS_TYPE = 1; + + /** + * Constant to signal that the created type is a interface. + * @since 3.1 + */ + public static final int INTERFACE_TYPE = 2; + + /** + * Constant to signal that the created type is an enum. + * @since 3.1 + */ + public static final int ENUM_TYPE = 3; + + /** + * Constant to signal that the created type is an annotation. + * @since 3.1 + */ + public static final int ANNOTATION_TYPE = 4; + + /** + * Constant to signal that the created type is an record. + * @since 3.21 + * @noreference This field is not intended to be referenced by clients. + */ + public static final int RECORD_TYPE = 5; + + /** Public access flag. See The Java Virtual Machine Specification for more details. */ + public int F_PUBLIC = Flags.AccPublic; + /** Private access flag. See The Java Virtual Machine Specification for more details. */ + public int F_PRIVATE = Flags.AccPrivate; + /** Protected access flag. See The Java Virtual Machine Specification for more details. */ + public int F_PROTECTED = Flags.AccProtected; + /** Static access flag. See The Java Virtual Machine Specification for more details. */ + public int F_STATIC = Flags.AccStatic; + /** Final access flag. See The Java Virtual Machine Specification for more details. */ + public int F_FINAL = Flags.AccFinal; + /** Abstract property flag. See The Java Virtual Machine Specification for more details. */ + public int F_ABSTRACT = Flags.AccAbstract; + /** Non-Sealed access Flag. */ + private int F_NON_SEALED = Flags.AccNonSealed; + /** Sealed access Flag. */ + private int F_SEALED = Flags.AccSealed; + + /** Package dialog field. */ + private StringButtonStatusDialogField fPackageDialogField; + /** Enclosing type selection. */ private SelectionButtonDialogField fEnclosingTypeSelection; + /** Enclosing type dialog field. */ private StringButtonDialogField fEnclosingTypeDialogField; - + /** Can modify package flag. */ private boolean fCanModifyPackage; + /** Can modify enclosing type flag. */ private boolean fCanModifyEnclosingType; - + /** Current package. */ private IPackageFragment fCurrPackage; - + /** Current enclosing type. */ private IType fCurrEnclosingType; - /** - * a handle to the type to be created (does usually not exist, can be null) - */ - private IType fCurrType; + /** Super class. */ private IType fSuperClass; + /** Type name dialog field. */ private StringDialogField fTypeNameDialogField; - + /** Super class dialog field. */ private StringButtonDialogField fSuperClassDialogField; + /** Super interface dialog field. */ private ListDialogField fSuperInterfacesDialogField; - + /** Visibility modifier buttons. */ private SelectionButtonDialogFieldGroup fAccMdfButtons; + /** Other modifier buttons. */ private SelectionButtonDialogFieldGroup fOtherMdfButtons; + /** Sealed modifier buttons. */ private SelectionButtonDialogFieldGroup fSealedMdfButtons; - + /** Flag for sealed supported. */ private boolean fIsSealedSupported; - private boolean fResetSuperClass= true; - /** - * @noreference This field is not intended to be referenced by clients. - */ - protected SelectionButtonDialogField fAddCommentButton; - private boolean fUseAddCommentButtonValue; // used for compatibility: Wizards that don't show the comment button control - // will use the preferences settings - - private IType fCreatedType; - - private ITypeBinding fCreatedTypeBinding; - + /** Flag for super class reset. */ + private boolean fResetSuperClass = true; + /** Used for compatibility: Wizards that don't show the comment button control will use the preferences settings. */ + private boolean fUseAddCommentButtonValue; + /** The created types. */ + private List fCreatedTypes = new ArrayList<>(); + /** Current package completion processor. */ private JavaPackageCompletionProcessor fCurrPackageCompletionProcessor; + /** Enclosing type completion processor. */ private JavaTypeCompletionProcessor fEnclosingTypeCompletionProcessor; + /** Super class stub type context. */ private StubTypeContext fSuperClassStubTypeContext; + /** Super interface stub type context. */ private StubTypeContext fSuperInterfaceStubTypeContext; - + /** Enclosing type status. */ protected IStatus fEnclosingTypeStatus; + /** Package status. */ protected IStatus fPackageStatus; + /** Type name status. */ protected IStatus fTypeNameStatus; + /** Super class status. */ protected IStatus fSuperClassStatus; + /** Modifier status. */ protected IStatus fModifierStatus; + /** Super interfaces status. */ protected IStatus fSuperInterfacesStatus; /** + * This field is not intended to be referenced by clients. + * @noreference + */ + protected SelectionButtonDialogField fAddCommentButton; + + /** + * Sealed modifier status. * @since 3.25 */ protected IStatus fSealedModifierStatus; /** + * Sealed superclass status. * @since 3.25 */ protected IStatus fSealedSuperClassStatus; /** + * Sealed superinterfaces status. * @since 3.25 */ protected IStatus fSealedSuperInterfacesStatus; - + /** Type field adapter. */ private TypeFieldsAdapter fTypeFieldAdapter; - - private static final int PUBLIC_INDEX= 0, DEFAULT_INDEX= 1, PRIVATE_INDEX= 2, PROTECTED_INDEX= 3; - private static final int ABSTRACT_INDEX= 0, FINAL_INDEX= 1, STATIC_INDEX= 2, ENUM_ANNOT_STATIC_INDEX= 1; - private static final int SEALED_FINAL_INDEX= 3, SEALED_INDEX= 1, NON_SEALED_INDEX= 2; - + /** Type kind. */ private int fTypeKind; - /** - * Constant to signal that the created type is a class. - * @since 3.1 - */ - public static final int CLASS_TYPE = 1; - - /** - * Constant to signal that the created type is a interface. - * @since 3.1 - */ - public static final int INTERFACE_TYPE = 2; - - /** - * Constant to signal that the created type is an enum. - * @since 3.1 - */ - public static final int ENUM_TYPE = 3; - - /** - * Constant to signal that the created type is an annotation. - * @since 3.1 - */ - public static final int ANNOTATION_TYPE = 4; - - /** - * Constant to signal that the created type is an record. - * @since 3.21 - * @noreference This field is not intended to be referenced by clients. - */ - public static final int RECORD_TYPE = 5; - /** * Creates a new NewTypeWizardPage. - * - * @param isClass true if a new class is to be created; otherwise - * an interface is to be created + * @param isClass true if a new class is to be created; otherwise an interface is to be created * @param pageName the wizard page's name */ public NewTypeWizardPage(boolean isClass, String pageName) { @@ -526,152 +732,150 @@ public NewTypeWizardPage(boolean isClass, String pageName) { /** * Creates a new NewTypeWizardPage. - * * @param typeKind Signals the kind of the type to be created. Valid kinds are * {@link #CLASS_TYPE}, {@link #INTERFACE_TYPE}, {@link #ENUM_TYPE} and {@link #ANNOTATION_TYPE} * @param pageName the wizard page's name * @since 3.1 */ public NewTypeWizardPage(int typeKind, String pageName) { - super(pageName); - fTypeKind= typeKind; - - fCreatedType= null; - - fTypeFieldAdapter= new TypeFieldsAdapter(); - - fPackageDialogField= new StringButtonStatusDialogField(fTypeFieldAdapter); + super(pageName); + fTypeKind = typeKind; + fCreatedTypes.clear(); + fTypeFieldAdapter = new TypeFieldsAdapter(); + fPackageDialogField = new StringButtonStatusDialogField(fTypeFieldAdapter); fPackageDialogField.setDialogFieldListener(fTypeFieldAdapter); fPackageDialogField.setLabelText(getPackageLabel()); fPackageDialogField.setButtonLabel(NewWizardMessages.NewTypeWizardPage_package_button); fPackageDialogField.setStatusWidthHint(NewWizardMessages.NewTypeWizardPage_default); - fEnclosingTypeSelection= new SelectionButtonDialogField(SWT.CHECK); + fEnclosingTypeSelection = new SelectionButtonDialogField(SWT.CHECK); fEnclosingTypeSelection.setDialogFieldListener(fTypeFieldAdapter); fEnclosingTypeSelection.setLabelText(getEnclosingTypeLabel()); - fEnclosingTypeDialogField= new StringButtonDialogField(fTypeFieldAdapter); + fEnclosingTypeDialogField = new StringButtonDialogField(fTypeFieldAdapter); fEnclosingTypeDialogField.setDialogFieldListener(fTypeFieldAdapter); fEnclosingTypeDialogField.setButtonLabel(NewWizardMessages.NewTypeWizardPage_enclosing_button); - fTypeNameDialogField= new StringDialogField(); + fTypeNameDialogField = new StringDialogField(); fTypeNameDialogField.setDialogFieldListener(fTypeFieldAdapter); fTypeNameDialogField.setLabelText(getTypeNameLabel()); - fSuperClassDialogField= new StringButtonDialogField(fTypeFieldAdapter); + fSuperClassDialogField = new StringButtonDialogField(fTypeFieldAdapter); fSuperClassDialogField.setDialogFieldListener(fTypeFieldAdapter); fSuperClassDialogField.setLabelText(getSuperClassLabel()); fSuperClassDialogField.setButtonLabel(NewWizardMessages.NewTypeWizardPage_superclass_button); - String[] addButtons= new String[] { + String[] addButtons = new String[] { NewWizardMessages.NewTypeWizardPage_interfaces_add, /* 1 */ null, NewWizardMessages.NewTypeWizardPage_interfaces_remove }; - fSuperInterfacesDialogField= new ListDialogField<>(fTypeFieldAdapter, addButtons, new InterfacesListLabelProvider()); + fSuperInterfacesDialogField = new ListDialogField<>(fTypeFieldAdapter, addButtons, + new InterfacesListLabelProvider()); fSuperInterfacesDialogField.setDialogFieldListener(fTypeFieldAdapter); fSuperInterfacesDialogField.setTableColumns(new ListDialogField.ColumnsDescription(1, false)); fSuperInterfacesDialogField.setLabelText(getSuperInterfacesLabel()); fSuperInterfacesDialogField.setRemoveButtonIndex(2); - String[] buttonNames1= new String[] { + String[] buttonNames1 = new String[] { NewWizardMessages.NewTypeWizardPage_modifiers_public, NewWizardMessages.NewTypeWizardPage_modifiers_default, NewWizardMessages.NewTypeWizardPage_modifiers_private, NewWizardMessages.NewTypeWizardPage_modifiers_protected }; - fAccMdfButtons= new SelectionButtonDialogFieldGroup(SWT.RADIO, buttonNames1, 4); + fAccMdfButtons = new SelectionButtonDialogFieldGroup(SWT.RADIO, buttonNames1, 4); fAccMdfButtons.setDialogFieldListener(fTypeFieldAdapter); fAccMdfButtons.setLabelText(getModifiersLabel()); fAccMdfButtons.setSelection(0, true); String[] buttonNames2; if (fTypeKind == CLASS_TYPE) { - buttonNames2= new String[] { + buttonNames2 = new String[] { NewWizardMessages.NewTypeWizardPage_modifiers_abstract, NewWizardMessages.NewTypeWizardPage_modifiers_final, NewWizardMessages.NewTypeWizardPage_modifiers_static }; } else { - if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) { - buttonNames2= new String[] { + if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) { + buttonNames2 = new String[] { NewWizardMessages.NewTypeWizardPage_modifiers_abstract, NewWizardMessages.NewTypeWizardPage_modifiers_static - }; - } - else { + }; + } else { if (fTypeKind == RECORD_TYPE) { - buttonNames2= new String[] {NewWizardMessages.NewTypeWizardPage_modifiers_static}; - } else - buttonNames2= new String[] {}; + buttonNames2 = new String[] {NewWizardMessages.NewTypeWizardPage_modifiers_static}; + } else { + buttonNames2 = new String[] {}; + } } } - fOtherMdfButtons= new SelectionButtonDialogFieldGroup(SWT.CHECK, buttonNames2, 4); + fOtherMdfButtons = new SelectionButtonDialogFieldGroup(SWT.CHECK, buttonNames2, 4); fOtherMdfButtons.setDialogFieldListener(fTypeFieldAdapter); - fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX, false); fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX, false); fOtherMdfButtons.enableSelectionButton(STATIC_INDEX, false); if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) { - fOtherMdfButtons.enableSelectionButton(ABSTRACT_INDEX, false); - fOtherMdfButtons.enableSelectionButton(ENUM_ANNOT_STATIC_INDEX, false); + fOtherMdfButtons.enableSelectionButton(ABSTRACT_INDEX, false); + fOtherMdfButtons.enableSelectionButton(ENUM_ANNOT_STATIC_INDEX, false); } - fAddCommentButton= new SelectionButtonDialogField(SWT.CHECK); + fAddCommentButton = new SelectionButtonDialogField(SWT.CHECK); fAddCommentButton.setLabelText(NewWizardMessages.NewTypeWizardPage_addcomment_label); - fUseAddCommentButtonValue= false; // only used when enabled + fUseAddCommentButtonValue = false; // only used when enabled - fCurrPackageCompletionProcessor= new JavaPackageCompletionProcessor(); - fEnclosingTypeCompletionProcessor= new JavaTypeCompletionProcessor(false, false, true); + fCurrPackageCompletionProcessor = new JavaPackageCompletionProcessor(); + fEnclosingTypeCompletionProcessor = new JavaTypeCompletionProcessor(false, false, true); - fPackageStatus= new StatusInfo(); - fEnclosingTypeStatus= new StatusInfo(); + fPackageStatus = new StatusInfo(); + fEnclosingTypeStatus = new StatusInfo(); - fCanModifyPackage= true; - fCanModifyEnclosingType= true; + fCanModifyPackage = true; + fCanModifyEnclosingType = true; updateEnableState(); - fTypeNameStatus= new StatusInfo(); - fSuperClassStatus= new StatusInfo(); - fSuperInterfacesStatus= new StatusInfo(); - fModifierStatus= new StatusInfo(); - fSealedModifierStatus= new StatusInfo(); - fSealedSuperClassStatus= new StatusInfo(); - fSealedSuperInterfacesStatus= new StatusInfo(); + fTypeNameStatus = new StatusInfo(); + fSuperClassStatus = new StatusInfo(); + fSuperInterfacesStatus = new StatusInfo(); + fModifierStatus = new StatusInfo(); + fSealedModifierStatus = new StatusInfo(); + fSealedSuperClassStatus = new StatusInfo(); + fSealedSuperInterfacesStatus = new StatusInfo(); } + /** + * Initializes other buttons. + */ private void initOtherButtons() { - String[] buttonNames3= null; + String[] buttonNames3 = null; switch (fTypeKind) { case CLASS_TYPE: if (fIsSealedSupported) { - buttonNames3= new String[] { - NewWizardMessages.NewTypeWizardPage_none_label, - NewWizardMessages.NewTypeWizardPage_modifiers_sealed, - NewWizardMessages.NewTypeWizardPage_modifiers_non_sealed, - NewWizardMessages.NewTypeWizardPage_modifiers_final + buttonNames3 = new String[] { + NewWizardMessages.NewTypeWizardPage_none_label, + NewWizardMessages.NewTypeWizardPage_modifiers_sealed, + NewWizardMessages.NewTypeWizardPage_modifiers_non_sealed, + NewWizardMessages.NewTypeWizardPage_modifiers_final }; } break; case INTERFACE_TYPE: if (fIsSealedSupported) { - buttonNames3= new String[] { - NewWizardMessages.NewTypeWizardPage_none_label, - NewWizardMessages.NewTypeWizardPage_modifiers_sealed, - NewWizardMessages.NewTypeWizardPage_modifiers_non_sealed + buttonNames3 = new String[] { + NewWizardMessages.NewTypeWizardPage_none_label, + NewWizardMessages.NewTypeWizardPage_modifiers_sealed, + NewWizardMessages.NewTypeWizardPage_modifiers_non_sealed }; } - //$FALL-THROUGH$ + break; default: // do nothing - } - fSealedMdfButtons= null; + fSealedMdfButtons = null; if (buttonNames3 != null) { - fSealedMdfButtons= new SelectionButtonDialogFieldGroup(SWT.RADIO, buttonNames3, 4); + fSealedMdfButtons = new SelectionButtonDialogFieldGroup(SWT.RADIO, buttonNames3, 4); fSealedMdfButtons.setDialogFieldListener(fTypeFieldAdapter); fSealedMdfButtons.enableSelectionButton(SEALED_INDEX, false); fSealedMdfButtons.enableSelectionButton(NON_SEALED_INDEX, false); @@ -693,48 +897,46 @@ private void initOtherButtons() { /** * Initializes all fields provided by the page with a given selection. - * - * @param elem the selection used to initialize this page or - * null if no selection was available + * @param elem the selection used to initialize this page or null if no selection was available */ protected void initTypePage(IJavaElement elem) { - String initSuperclass= "java.lang.Object"; //$NON-NLS-1$ - ArrayList initSuperinterfaces= new ArrayList<>(5); + String initSuperclass = "java.lang.Object"; //$NON-NLS-1$ + ArrayList initSuperinterfaces = new ArrayList<>(5); - IJavaProject project= null; - IPackageFragment pack= null; - IType enclosingType= null; + IJavaProject project = null; + IPackageFragment pack = null; + IType enclosingType = null; if (elem != null) { - project= elem.getJavaProject(); + project = elem.getJavaProject(); setIsNonSealedSupported(project); - pack= (IPackageFragment) elem.getAncestor(IJavaElement.PACKAGE_FRAGMENT); + pack = (IPackageFragment) elem.getAncestor(IJavaElement.PACKAGE_FRAGMENT); if (pack == null && project != null) { - pack= getPackage(project); + pack = getPackage(project); } // evaluate the enclosing type - IType typeInCU= (IType) elem.getAncestor(IJavaElement.TYPE); + IType typeInCU = (IType) elem.getAncestor(IJavaElement.TYPE); if (typeInCU != null) { if (typeInCU.getCompilationUnit() != null) { - enclosingType= typeInCU; + enclosingType = typeInCU; } } else { - ICompilationUnit cu= (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT); + ICompilationUnit cu = (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT); if (cu != null) { - enclosingType= cu.findPrimaryType(); + enclosingType = cu.findPrimaryType(); } } try { - IType type= null; + IType type = null; if (elem.getElementType() == IJavaElement.TYPE) { - type= (IType)elem; + type = (IType) elem; if (type.exists()) { - String superName= SuperInterfaceSelectionDialog.getNameWithTypeParameters(type); + String superName = SuperInterfaceSelectionDialog.getNameWithTypeParameters(type); if (type.isInterface()) { initSuperinterfaces.add(superName); } else { - initSuperclass= superName; + initSuperclass = superName; } } } @@ -744,13 +946,13 @@ protected void initTypePage(IJavaElement elem) { } } - String typeName= ""; //$NON-NLS-1$ + String typeName = ""; //$NON-NLS-1$ - ITextSelection selection= getCurrentTextSelection(); + ITextSelection selection = getCurrentTextSelection(); if (selection != null) { - String text= selection.getText(); + String text = selection.getText(); if (text != null && validateJavaTypeName(text, project).isOK()) { - typeName= getUniqueJavaTypeName (pack, text); + typeName = getUniqueJavaTypeName(pack, text); } } @@ -767,37 +969,36 @@ protected void initTypePage(IJavaElement elem) { /** * Generate a unique type name for some initially given name under the given package fragment. - * * @param pack the package fragment under which to check for uniqueness * @param name the type name to check for uniqueness * @return a type name string that is unique under the given package fragment. If the initial - * type name is not unique, it is suffixed with a number greater than or equal to 2. + * type name is not unique, it is suffixed with a number greater than or equal to 2. * @since 3.17 */ protected String getUniqueJavaTypeName(IPackageFragment pack, String name) { - String typeName= name; + String typeName = name; if (pack != null) { - IResource resource= null; - boolean initial= true; + IResource resource = null; + boolean initial = true; while (resource == null || resource.exists()) { - typeName= Signature.getSimpleName(typeName); - Matcher m= NUM_PATTERN.matcher(typeName); + typeName = Signature.getSimpleName(typeName); + Matcher m = NUM_PATTERN.matcher(typeName); if (m.find()) { // String ends with a number: increment it by 1 - BigDecimal newNumber= null; + BigDecimal newNumber = null; try { - newNumber= new BigDecimal(m.group()).add(new BigDecimal(1)); - typeName= m.replaceFirst(newNumber.toPlainString()); + newNumber = new BigDecimal(m.group()).add(new BigDecimal(1)); + typeName = m.replaceFirst(newNumber.toPlainString()); } catch (NumberFormatException e) { - typeName= m.replaceFirst("2"); //$NON-NLS-1$ + typeName = m.replaceFirst("2"); //$NON-NLS-1$ } } else { - typeName+= (initial ? "" : "2"); //$NON-NLS-1$ //$NON-NLS-2$ - initial= false; + typeName += (initial ? "" : "2"); //$NON-NLS-1$ //$NON-NLS-2$ + initial = false; } - ICompilationUnit cu= pack.getCompilationUnit(getCompilationUnitName(typeName)); - resource= cu.getResource(); + ICompilationUnit cu = pack.getCompilationUnit(getCompilationUnitName(typeName)); + resource = cu.getResource(); } } return typeName; @@ -811,42 +1012,40 @@ protected String getUniqueJavaTypeName(IPackageFragment pack, String name) { * package fragment's name. null is returned if none of the above is applicable. * * @param javaProject the containing Java project of the selection used to initialize this page - * * @return the package fragment to be pre-filled in this page or null if no - * suitable package can be suggested for the given project - * + * suitable package can be suggested for the given project * @since 3.9 */ private IPackageFragment getPackage(IJavaProject javaProject) { - String packName= null; - final IPackageFragmentRoot pkgFragmentRoot= getPackageFragmentRoot(); - IJavaElement[] packages= null; + String packName = null; + final IPackageFragmentRoot pkgFragmentRoot = getPackageFragmentRoot(); + IJavaElement[] packages = null; try { if (pkgFragmentRoot != null && pkgFragmentRoot.exists()) { - packages= pkgFragmentRoot.getChildren(); + packages = pkgFragmentRoot.getChildren(); if (packages.length == 1) { // only default package -> use Project name - packName= javaProject.getElementName(); + packName = javaProject.getElementName(); // validate package name - IStatus status= validatePackageName(packName, javaProject); + IStatus status = validatePackageName(packName, javaProject); if (status.getSeverity() == IStatus.OK) { return pkgFragmentRoot.getPackageFragment(packName); } } else { - int noOfPackages= 0; - IPackageFragment thePackage= null; + int noOfPackages = 0; + IPackageFragment thePackage = null; for (final IJavaElement pack : packages) { - IPackageFragment pkg= (IPackageFragment) pack; + IPackageFragment pkg = (IPackageFragment) pack; // ignoring empty parent packages and default package if ((!pkg.hasSubpackages() || pkg.hasChildren()) && !pkg.isDefaultPackage()) { noOfPackages++; - thePackage= pkg; + thePackage = pkg; if (noOfPackages > 1) { return null; } } } if (thePackage != null) { // use package name - packName= thePackage.getElementName(); + packName = thePackage.getElementName(); return pkgFragmentRoot.getPackageFragment(packName); } } @@ -857,6 +1056,12 @@ private IPackageFragment getPackage(IJavaProject javaProject) { return null; } + /** + * Validates a Java type name. + * @param text Name to validate + * @param project Java project + * @return Validation status + */ private static IStatus validateJavaTypeName(String text, IJavaProject project) { if (project == null || !project.exists()) { return JavaConventions.validateJavaTypeName(text, JavaCore.VERSION_1_3, JavaCore.VERSION_1_3, null); @@ -864,6 +1069,12 @@ private static IStatus validateJavaTypeName(String text, IJavaProject project) { return JavaConventionsUtil.validateJavaTypeName(text, project); } + /** + * Validates a Java package name. + * @param text Name to validate + * @param project Java project + * @return Validation status + */ private static IStatus validatePackageName(String text, IJavaProject project) { if (project == null || !project.exists()) { return JavaConventions.validatePackageName(text, JavaCore.VERSION_1_3, JavaCore.VERSION_1_3); @@ -875,7 +1086,6 @@ private static IStatus validatePackageName(String text, IJavaProject project) { /** * Returns the label that is used for the package input field. - * * @return the label that is used for the package input field. * @since 3.2 */ @@ -885,7 +1095,6 @@ protected String getPackageLabel() { /** * Returns the label that is used for the enclosing type input field. - * * @return the label that is used for the enclosing type input field. * @since 3.2 */ @@ -895,7 +1104,6 @@ protected String getEnclosingTypeLabel() { /** * Returns the label that is used for the type name input field. - * * @return the label that is used for the type name input field. * @since 3.2 */ @@ -905,7 +1113,6 @@ protected String getTypeNameLabel() { /** * Returns the label that is used for the modifiers input field. - * * @return the label that is used for the modifiers input field * @since 3.2 */ @@ -915,7 +1122,6 @@ protected String getModifiersLabel() { /** * Returns the label that is used for the super class input field. - * * @return the label that is used for the super class input field. * @since 3.2 */ @@ -925,36 +1131,34 @@ protected String getSuperClassLabel() { /** * Returns the label that is used for the super interfaces input field. - * * @return the label that is used for the super interfaces input field. * @since 3.2 */ protected String getSuperInterfacesLabel() { - if (fTypeKind != INTERFACE_TYPE) - return NewWizardMessages.NewTypeWizardPage_interfaces_class_label; - return NewWizardMessages.NewTypeWizardPage_interfaces_ifc_label; + if (fTypeKind != INTERFACE_TYPE) { + return NewWizardMessages.NewTypeWizardPage_interfaces_class_label; + } + return NewWizardMessages.NewTypeWizardPage_interfaces_ifc_label; } /** * Creates a separator line. Expects a GridLayout with at least 1 column. - * * @param composite the parent composite * @param nColumns number of columns to span */ protected void createSeparator(Composite composite, int nColumns) { - (new Separator(SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(composite, nColumns, convertHeightInCharsToPixels(1)); + (new Separator(SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(composite, nColumns, + convertHeightInCharsToPixels(1)); } /** - * Creates the controls for the package name field. Expects a GridLayout with at - * least 4 columns. - * + * Creates the controls for the package name field. Expects a GridLayout with at least 4 columns. * @param composite the parent composite * @param nColumns number of columns to span */ protected void createPackageControls(Composite composite, int nColumns) { fPackageDialogField.doFillIntoGrid(composite, nColumns); - Text text= fPackageDialogField.getTextControl(null); + Text text = fPackageDialogField.getTextControl(null); BidiUtils.applyBidiProcessing(text, StructuredTextTypeHandlerFactory.JAVA); LayoutUtil.setWidthHint(text, getMaxFieldWidth()); LayoutUtil.setHorizontalGrabbing(text); @@ -965,30 +1169,29 @@ protected void createPackageControls(Composite composite, int nColumns) { /** * Creates the controls for the enclosing type name field. Expects a GridLayout with at * least 4 columns. - * * @param composite the parent composite * @param nColumns number of columns to span */ protected void createEnclosingTypeControls(Composite composite, int nColumns) { // #6891 - Composite tabGroup= new Composite(composite, SWT.NONE); - GridLayout layout= new GridLayout(); - layout.marginWidth= 0; - layout.marginHeight= 0; + Composite tabGroup = new Composite(composite, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; tabGroup.setLayout(layout); fEnclosingTypeSelection.doFillIntoGrid(tabGroup, 1); - Text text= fEnclosingTypeDialogField.getTextControl(composite); + Text text = fEnclosingTypeDialogField.getTextControl(composite); SWTUtil.setAccessibilityText(text, NewWizardMessages.NewTypeWizardPage_enclosing_field_description); - GridData gd= new GridData(GridData.FILL_HORIZONTAL); - gd.widthHint= getMaxFieldWidth(); - gd.horizontalSpan= 2; + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.widthHint = getMaxFieldWidth(); + gd.horizontalSpan = 2; text.setLayoutData(gd); - Button button= fEnclosingTypeDialogField.getChangeControl(composite); - gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL); + Button button = fEnclosingTypeDialogField.getChangeControl(composite); + gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); gd.widthHint = SWTUtil.getButtonWidthHint(button); button.setLayoutData(gd); ControlContentAssistHelper.createTextContentAssistant(text, fEnclosingTypeCompletionProcessor); @@ -996,9 +1199,7 @@ protected void createEnclosingTypeControls(Composite composite, int nColumns) { } /** - * Creates the controls for the type name field. Expects a GridLayout with at - * least 2 columns. - * + * Creates the controls for the type name field. Expects a GridLayout with at least 2 columns. * @param composite the parent composite * @param nColumns number of columns to span */ @@ -1006,23 +1207,29 @@ protected void createTypeNameControls(Composite composite, int nColumns) { fTypeNameDialogField.doFillIntoGrid(composite, nColumns - 1); DialogField.createEmptySpace(composite); - Text text= fTypeNameDialogField.getTextControl(null); + Text text = fTypeNameDialogField.getTextControl(null); LayoutUtil.setWidthHint(text, getMaxFieldWidth()); TextFieldNavigationHandler.install(text); + var textDeco = new ControlDecoration(text, SWT.TOP | SWT.LEFT); + var infoDeco = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_INFORMATION); + textDeco.setDescriptionText(NewWizardMessages.NewTypeWizardPage_info_NamesSeparatedBySemicolon); + textDeco.setImage(infoDeco.getImage()); + text.addVerifyListener(e -> { - if (fCanModifyPackage && ! fEnclosingTypeSelection.isSelected() && e.start == 0 && e.end == ((Text) e.widget).getCharCount()) { - String typeNameWithoutParameters= getTypeNameWithoutParameters(getTypeNameWithoutExtension(e.text)); - int lastDot= typeNameWithoutParameters.lastIndexOf('.'); - if (lastDot == -1 || lastDot == typeNameWithoutParameters.length() - 1) + if (fCanModifyPackage && ! fEnclosingTypeSelection.isSelected() + && e.start == 0 && e.end == ((Text) e.widget).getCharCount()) { + String typeNameWithoutParameters = getTypeNameWithoutParameters(getTypeNameWithoutExtension(e.text)); + int lastDot = typeNameWithoutParameters.lastIndexOf('.'); + if (lastDot == -1 || lastDot == typeNameWithoutParameters.length() - 1) { return; - - String pack= typeNameWithoutParameters.substring(0, lastDot); - if (validatePackageName(pack, null).getSeverity() == IStatus.ERROR) + } + String pack = typeNameWithoutParameters.substring(0, lastDot); + if (validatePackageName(pack, null).getSeverity() == IStatus.ERROR) { return; - + } fPackageDialogField.setText(pack); - e.text= e.text.substring(lastDot + 1); + e.text = e.text.substring(lastDot + 1); } }); } @@ -1030,16 +1237,15 @@ protected void createTypeNameControls(Composite composite, int nColumns) { /** * Creates the controls for the modifiers radio/checkbox buttons. Expects a * GridLayout with at least 3 columns. - * * @param composite the parent composite * @param nColumns number of columns to span */ protected void createModifierControls(Composite composite, int nColumns) { LayoutUtil.setHorizontalSpan(fAccMdfButtons.getLabelControl(composite), 1); - Control control= fAccMdfButtons.getSelectionButtonsGroup(composite); - GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL); - gd.horizontalSpan= nColumns - 2; + Control control = fAccMdfButtons.getSelectionButtonsGroup(composite); + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + gd.horizontalSpan = nColumns - 2; control.setLayoutData(gd); DialogField.createEmptySpace(composite); @@ -1047,20 +1253,20 @@ protected void createModifierControls(Composite composite, int nColumns) { if (fTypeKind == CLASS_TYPE || fTypeKind == INTERFACE_TYPE) { DialogField.createEmptySpace(composite); - control= fOtherMdfButtons.getSelectionButtonsGroup(composite); - gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL); + control = fOtherMdfButtons.getSelectionButtonsGroup(composite); + gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); if (fSealedMdfButtons != null) { - gd.horizontalSpan= nColumns - 1; + gd.horizontalSpan = nColumns - 1; } else { - gd.horizontalSpan= nColumns - 2; + gd.horizontalSpan = nColumns - 2; } control.setLayoutData(gd); if (fSealedMdfButtons != null) { DialogField.createEmptySpace(composite); - control= fSealedMdfButtons.getSelectionButtonsGroup(composite); - gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL); - gd.horizontalSpan= nColumns - 2; + control = fSealedMdfButtons.getSelectionButtonsGroup(composite); + gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + gd.horizontalSpan = nColumns - 2; control.setLayoutData(gd); } @@ -1071,21 +1277,20 @@ protected void createModifierControls(Composite composite, int nColumns) { /** * Creates the controls for the superclass name field. Expects a GridLayout * with at least 3 columns. - * * @param composite the parent composite * @param nColumns number of columns to span */ protected void createSuperClassControls(Composite composite, int nColumns) { fSuperClassDialogField.doFillIntoGrid(composite, nColumns); - Text text= fSuperClassDialogField.getTextControl(null); + Text text = fSuperClassDialogField.getTextControl(null); LayoutUtil.setWidthHint(text, getMaxFieldWidth()); BidiUtils.applyBidiProcessing(text, StructuredTextTypeHandlerFactory.JAVA); - JavaTypeCompletionProcessor superClassCompletionProcessor= new JavaTypeCompletionProcessor(false, false, true); + JavaTypeCompletionProcessor superClassCompletionProcessor = new JavaTypeCompletionProcessor(false, false, true); superClassCompletionProcessor.setCompletionContextRequestor(new CompletionContextRequestor() { @Override public StubTypeContext getStubTypeContext() { - return getSuperClassStubTypeContext(); + return getSuperClassStubTypeContext(null); } }); @@ -1094,46 +1299,46 @@ public StubTypeContext getStubTypeContext() { } /** - * Creates the controls for the superclass name field. Expects a GridLayout with - * at least 3 columns. - * + * Creates the controls for the superclass name field. Expects a GridLayout with at least 3 columns. * @param composite the parent composite * @param nColumns number of columns to span */ protected void createSuperInterfacesControls(Composite composite, int nColumns) { - final String INTERFACE= "interface"; //$NON-NLS-1$ fSuperInterfacesDialogField.doFillIntoGrid(composite, nColumns); - final TableViewer tableViewer= fSuperInterfacesDialogField.getTableViewer(); - tableViewer.setColumnProperties(new String[] {INTERFACE}); + final TableViewer tableViewer = fSuperInterfacesDialogField.getTableViewer(); + tableViewer.setColumnProperties(new String[] {"interface"}); //$NON-NLS-1$ - TableTextCellEditor cellEditor= new TableTextCellEditor(tableViewer, 0) { + TableTextCellEditor cellEditor = new TableTextCellEditor(tableViewer, 0) { @Override protected Control createControl(Composite parent) { - Control control= super.createControl(parent); + Control control = super.createControl(parent); BidiUtils.applyBidiProcessing(text, StructuredTextTypeHandlerFactory.JAVA); return control; } - @Override + /** + * Sets the focus. + */ + @Override protected void doSetFocus() { - if (text != null) { - text.setFocus(); - text.setSelection(text.getText().length()); - checkSelection(); - checkDeleteable(); - checkSelectable(); - } - } + if (text != null) { + text.setFocus(); + text.setSelection(text.getText().length()); + checkSelection(); + checkDeleteable(); + checkSelectable(); + } + } }; - JavaTypeCompletionProcessor superInterfaceCompletionProcessor= new JavaTypeCompletionProcessor(false, false, true); + var superInterfaceCompletionProcessor = new JavaTypeCompletionProcessor(false, false, true); superInterfaceCompletionProcessor.setCompletionContextRequestor(new CompletionContextRequestor() { @Override public StubTypeContext getStubTypeContext() { - return getSuperInterfacesStubTypeContext(); + return getSuperInterfacesStubTypeContext(null); } }); - SubjectControlContentAssistant contentAssistant= ControlContentAssistHelper.createJavaContentAssistant(superInterfaceCompletionProcessor); - Text cellEditorText= cellEditor.getText(); + var contentAssistant = ControlContentAssistHelper.createJavaContentAssistant(superInterfaceCompletionProcessor); + Text cellEditorText = cellEditor.getText(); ContentAssistHandler.createHandlerForText(cellEditorText, contentAssistant); TextFieldNavigationHandler.install(cellEditorText); cellEditor.setContentAssistant(contentAssistant); @@ -1142,12 +1347,13 @@ public StubTypeContext getStubTypeContext() { tableViewer.setCellModifier(new ICellModifier() { @Override public void modify(Object element, String property, Object value) { - if (element instanceof Item) - element = ((Item) element).getData(); + if (element instanceof Item it) { + element = it.getData(); + } - IType interfaceType= null; + IType interfaceType = null; try { - interfaceType= findType(getJavaProject(), (String) value); + interfaceType = findType(getJavaProject(), (String) value); } catch (JavaModelException e) { //do nothing } @@ -1168,45 +1374,43 @@ public boolean canModify(Object element, String property) { @Override public void keyPressed(KeyEvent event) { if (event.keyCode == SWT.F2 && event.stateMask == 0) { - ISelection selection= tableViewer.getSelection(); - if (! (selection instanceof IStructuredSelection)) + ISelection selection = tableViewer.getSelection(); + if (! (selection instanceof IStructuredSelection)) { return; - IStructuredSelection structuredSelection= (IStructuredSelection) selection; + } + IStructuredSelection structuredSelection = (IStructuredSelection) selection; tableViewer.editElement(structuredSelection.getFirstElement(), 0); } } }); - GridData gd= (GridData) fSuperInterfacesDialogField.getListControl(null).getLayoutData(); + GridData gd = (GridData) fSuperInterfacesDialogField.getListControl(null).getLayoutData(); if (fTypeKind == CLASS_TYPE) { - gd.heightHint= convertHeightInCharsToPixels(3); + gd.heightHint = convertHeightInCharsToPixels(3); } else { - gd.heightHint= convertHeightInCharsToPixels(6); + gd.heightHint = convertHeightInCharsToPixels(6); } - gd.grabExcessVerticalSpace= false; - gd.widthHint= getMaxFieldWidth(); + gd.grabExcessVerticalSpace = false; + gd.widthHint = getMaxFieldWidth(); } /** - * Creates the controls for the preference page links. Expects a GridLayout with - * at least 3 columns. - * + * Creates the controls for the preference page links. Expects a GridLayout with at least 3 columns. * @param composite the parent composite * @param nColumns number of columns to span - * * @since 3.1 */ protected void createCommentControls(Composite composite, int nColumns) { - Link link= new Link(composite, SWT.NONE); - link.setText(NewWizardMessages.NewTypeWizardPage_addcomment_description); - link.addSelectionListener(new TypeFieldsAdapter()); - link.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false, nColumns, 1)); + Link link = new Link(composite, SWT.NONE); + link.setText(NewWizardMessages.NewTypeWizardPage_addcomment_description); + link.addSelectionListener(new TypeFieldsAdapter()); + link.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false, nColumns, 1)); DialogField.createEmptySpace(composite); fAddCommentButton.doFillIntoGrid(composite, nColumns - 1); } + /** - * Creates the comment and link in the single line for the preference page links. Expects a - * GridLayout with at least 2 columns. - * + * Creates the comment and link in the single line for the preference page links. Expects a + * GridLayout with at least 2 columns. * @param composite the parent composite * @param nColumns number of columns to span * @param isModule if it is module or package @@ -1214,21 +1418,20 @@ protected void createCommentControls(Composite composite, int nColumns) { * @since 3.18 */ protected Link createCommentWithLinkControls(Composite composite, int nColumns, boolean isModule) { - if(isModule) + if (isModule) { DialogField.createEmptySpace(composite); + } fAddCommentButton.doFillIntoGridWithoutMargin(composite, nColumns, !isModule); - Link link= new Link(composite, SWT.NONE); + Link link = new Link(composite, SWT.NONE); link.setText(NewWizardMessages.NewTypeWizardPage_addcomment_description2); link.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false)); - if(!isModule) { + if (!isModule) { fAddCommentButton.setEnabled(false); } link.addSelectionListener(new TypeFieldsAdapter()); return link; } - - /** * Sets the focus on the type name input field. */ @@ -1240,107 +1443,79 @@ protected void setFocus() { } } - // -------- TypeFieldsAdapter -------- - - private class TypeFieldsAdapter implements IStringButtonAdapter, IDialogFieldListener, IListAdapter, SelectionListener { - - // -------- IStringButtonAdapter - @Override - public void changeControlPressed(DialogField field) { - typePageChangeControlPressed(field); - } - - // -------- IListAdapter - @Override - public void customButtonPressed(ListDialogField field, int index) { - typePageCustomButtonPressed(field, index); - } - - @Override - public void selectionChanged(ListDialogField field) {} - - // -------- IDialogFieldListener - @Override - public void dialogFieldChanged(DialogField field) { - typePageDialogFieldChanged(field); - } - - @Override - public void doubleClicked(ListDialogField field) { - } - - - @Override - public void widgetSelected(SelectionEvent e) { - typePageLinkActivated(); - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - typePageLinkActivated(); - } - } - + /** + * Hook when type page link is activated. + */ private void typePageLinkActivated() { - IJavaProject project= getJavaProject(); + IJavaProject project = getJavaProject(); if (project != null) { - PreferenceDialog dialog= PreferencesUtil.createPropertyDialogOn(getShell(), project.getProject(), CodeTemplatePreferencePage.PROP_ID, null, null); + PreferenceDialog dialog = PreferencesUtil.createPropertyDialogOn(getShell(), project.getProject(), + CodeTemplatePreferencePage.PROP_ID, null, null); dialog.open(); } else { - String title= NewWizardMessages.NewTypeWizardPage_configure_templates_title; - String message= NewWizardMessages.NewTypeWizardPage_configure_templates_message; + String title = NewWizardMessages.NewTypeWizardPage_configure_templates_title; + String message = NewWizardMessages.NewTypeWizardPage_configure_templates_message; MessageDialog.openInformation(getShell(), title, message); } } + /** + * Type page change control was pressed. + * @param field Dialog field + */ private void typePageChangeControlPressed(DialogField field) { if (field == fPackageDialogField) { - IPackageFragment pack= choosePackage(); + IPackageFragment pack = choosePackage(); if (pack != null) { fPackageDialogField.setText(pack.getElementName()); } } else if (field == fEnclosingTypeDialogField) { - IType type= chooseEnclosingType(); + IType type = chooseEnclosingType(); if (type != null) { setEnclosingType(type); } } else if (field == fSuperClassDialogField) { - IType type= chooseSuperClass(); + IType type = chooseSuperClass(); setSuperClass(type); } } + /** + * Type page custom button was pressed. + * @param field Dialog field + * @param index The index + */ private void typePageCustomButtonPressed(DialogField field, int index) { if (field == fSuperInterfacesDialogField && index == 0) { chooseSuperInterfaces(); - List interfaces= fSuperInterfacesDialogField.getElements(); + List interfaces = fSuperInterfacesDialogField.getElements(); if (!interfaces.isEmpty()) { - Object element= interfaces.get(interfaces.size() - 1); + Object element = interfaces.get(interfaces.size() - 1); fSuperInterfacesDialogField.editElement(element); } } } - /* - * A field on the type has changed. The fields' status and all dependent - * status are updated. + /** + * A field on the type has changed. The fields' status and all dependent status are updated. + * @param field Dialog field */ private void typePageDialogFieldChanged(DialogField field) { - String fieldName= null; + String fieldName = null; if (field == fPackageDialogField) { - fPackageStatus= packageChanged(); + fPackageStatus = packageChanged(); updatePackageStatusLabel(); - fTypeNameStatus= typeNameChanged(); - fSuperClassStatus= superClassChanged(); - fieldName= PACKAGE; + fTypeNameStatus = typeNameChanged(); + fSuperClassStatus = superClassChanged(); + fieldName = PACKAGE; } else if (field == fEnclosingTypeDialogField) { - fEnclosingTypeStatus= enclosingTypeChanged(); - fTypeNameStatus= typeNameChanged(); - fSuperClassStatus= superClassChanged(); - fieldName= ENCLOSING; + fEnclosingTypeStatus = enclosingTypeChanged(); + fTypeNameStatus = typeNameChanged(); + fSuperClassStatus = superClassChanged(); + fieldName = ENCLOSING; } else if (field == fEnclosingTypeSelection) { updateEnableState(); - boolean isEnclosedType= isEnclosingTypeSelected(); + boolean isEnclosedType = isEnclosingTypeSelected(); if (!isEnclosedType) { if (fAccMdfButtons.isSelected(PRIVATE_INDEX) || fAccMdfButtons.isSelected(PROTECTED_INDEX)) { fAccMdfButtons.setSelection(PRIVATE_INDEX, false); @@ -1354,29 +1529,29 @@ private void typePageDialogFieldChanged(DialogField field) { fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX, isEnclosedType); fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX, isEnclosedType); fOtherMdfButtons.enableSelectionButton(STATIC_INDEX, isEnclosedType); - fTypeNameStatus= typeNameChanged(); - fSuperClassStatus= superClassChanged(); - fieldName= ENCLOSINGSELECTION; + fTypeNameStatus = typeNameChanged(); + fSuperClassStatus = superClassChanged(); + fieldName = ENCLOSINGSELECTION; } else if (field == fTypeNameDialogField) { - fTypeNameStatus= typeNameChanged(); - fieldName= TYPENAME; + fTypeNameStatus = typeNameChanged(); + fieldName = TYPENAME; } else if (field == fSuperClassDialogField) { setSuperClassType(); - fSuperClassStatus= superClassChanged(); - fSealedModifierStatus= sealedModifiersChanged(); - fieldName= SUPER; + fSuperClassStatus = superClassChanged(); + fSealedModifierStatus = sealedModifiersChanged(); + fieldName = SUPER; } else if (field == fSuperInterfacesDialogField) { - fSuperInterfacesStatus= superInterfacesChanged(); - fSealedModifierStatus= sealedModifiersChanged(); - fieldName= INTERFACES; + fSuperInterfacesStatus = superInterfacesChanged(); + fSealedModifierStatus = sealedModifiersChanged(); + fieldName = INTERFACES; } else if (field == fOtherMdfButtons || field == fAccMdfButtons) { - fModifierStatus= modifiersChanged(); - fieldName= MODIFIERS; + fModifierStatus = modifiersChanged(); + fieldName = MODIFIERS; } else if (field == fSealedMdfButtons) { - fSealedModifierStatus= sealedModifiersChanged(); - fieldName= SEALEDMODIFIERS; + fSealedModifierStatus = sealedModifiersChanged(); + fieldName = SEALEDMODIFIERS; } else { - fieldName= METHODS; + fieldName = METHODS; } // tell all others handleFieldChanged(fieldName); @@ -1384,19 +1559,20 @@ private void typePageDialogFieldChanged(DialogField field) { // -------- update message ---------------- - /* - * @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(String) + /** + * {@inheritDoc} + * @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(java.lang.String) */ @Override protected void handleFieldChanged(String fieldName) { super.handleFieldChanged(fieldName); if (CONTAINER.equals(fieldName)) { - fPackageStatus= packageChanged(); - fEnclosingTypeStatus= enclosingTypeChanged(); - fTypeNameStatus= typeNameChanged(); - fSuperClassStatus= superClassChanged(); - fSuperInterfacesStatus= superInterfacesChanged(); - fSealedModifierStatus= sealedModifiersChanged(); + fPackageStatus = packageChanged(); + fEnclosingTypeStatus = enclosingTypeChanged(); + fTypeNameStatus = typeNameChanged(); + fSuperClassStatus = superClassChanged(); + fSuperInterfacesStatus = superInterfacesChanged(); + fSealedModifierStatus = sealedModifiersChanged(); } } @@ -1404,7 +1580,6 @@ protected void handleFieldChanged(String fieldName) { /** * Returns the text of the package input field. - * * @return the text of the package input field */ public String getPackageText() { @@ -1413,43 +1588,32 @@ public String getPackageText() { /** * Returns the text of the enclosing type input field. - * * @return the text of the enclosing type input field */ public String getEnclosingTypeText() { return fEnclosingTypeDialogField.getText(); } - /** * Returns the package fragment corresponding to the current input. - * - * @return a package fragment or null if the input - * could not be resolved. + * @return a package fragment or null if the input could not be resolved. */ public IPackageFragment getPackageFragment() { if (!isEnclosingTypeSelected()) { return fCurrPackage; - } else { - if (fCurrEnclosingType != null) { - return fCurrEnclosingType.getPackageFragment(); - } } - return null; + return fCurrEnclosingType == null ? null : fCurrEnclosingType.getPackageFragment(); } /** - * Sets the package fragment to the given value. The method updates the model - * and the text of the control. - * + * Sets the package fragment to the given value. The method updates the model and the text of the control. * @param pack the package fragment to be set - * @param canBeModified if true the package fragment is - * editable; otherwise it is read-only. + * @param canBeModified if true the package fragment is editable; otherwise it is read-only. */ public void setPackageFragment(IPackageFragment pack, boolean canBeModified) { - fCurrPackage= pack; - fCanModifyPackage= canBeModified; - String str= (pack == null) ? "" : pack.getElementName(); //$NON-NLS-1$ + fCurrPackage = pack; + fCanModifyPackage = canBeModified; + String str = (pack == null) ? "" : pack.getElementName(); //$NON-NLS-1$ fPackageDialogField.setText(str); updateEnableState(); if (fCurrPackage != null) { @@ -1459,36 +1623,28 @@ public void setPackageFragment(IPackageFragment pack, boolean canBeModified) { /** * Returns the enclosing type corresponding to the current input. - * - * @return the enclosing type or null if the enclosing type is - * not selected or the input could not be resolved + * @return Enclosing type or null if the enclosing type is not selected or the input could not be + * resolved */ public IType getEnclosingType() { - if (isEnclosingTypeSelected()) { - return fCurrEnclosingType; - } - return null; + return isEnclosingTypeSelected() ? fCurrEnclosingType : null; } /** - * Sets the enclosing type. The method updates the underlying model - * and the text of the control. - * + * Sets the enclosing type. The method updates the underlying model and the text of the control. * @param type the enclosing type - * @param canBeModified if true the enclosing type field is - * editable; otherwise it is read-only. + * @param canBeModified if true the enclosing type field is editable; otherwise it is read-only. */ public void setEnclosingType(IType type, boolean canBeModified) { - fCurrEnclosingType= type; - fCanModifyEnclosingType= canBeModified; - String str= (type == null) ? "" : type.getFullyQualifiedName('.'); //$NON-NLS-1$ + fCurrEnclosingType = type; + fCanModifyEnclosingType = canBeModified; + String str = (type == null) ? "" : type.getFullyQualifiedName('.'); //$NON-NLS-1$ fEnclosingTypeDialogField.setText(str); updateEnableState(); } /** * Returns the selection state of the enclosing type checkbox. - * * @return the selection state of the enclosing type checkbox */ public boolean isEnclosingTypeSelected() { @@ -1497,7 +1653,6 @@ public boolean isEnclosingTypeSelected() { /** * Sets the enclosing type checkbox's selection state. - * * @param isSelected the checkbox's selection state * @param canBeModified if true the enclosing type checkbox is * modifiable; otherwise it is read-only. @@ -1511,30 +1666,30 @@ public void setEnclosingTypeSelection(boolean isSelected, boolean canBeModified) /** * Returns the type name entered into the type input field (without the default file extension * java, if entered). - * * @return the type name */ public String getTypeName() { - String typeNameWithExtension= fTypeNameDialogField.getText(); + String typeNameWithExtension = fTypeNameDialogField.getText(); return getTypeNameWithoutExtension(typeNameWithExtension); } + /** + * Returns the type name without extension (.java). + * @param typeNameWithExtension Type name possibly with extension + * @return Type name without extension + */ private String getTypeNameWithoutExtension(String typeNameWithExtension) { if (!typeNameWithExtension.endsWith(JavaModelUtil.DEFAULT_CU_SUFFIX)) { return typeNameWithExtension; - } else { - int extensionOffset= typeNameWithExtension.lastIndexOf(JavaModelUtil.DEFAULT_CU_SUFFIX); - return typeNameWithExtension.substring(0, extensionOffset); } + int extensionOffset = typeNameWithExtension.lastIndexOf(JavaModelUtil.DEFAULT_CU_SUFFIX); + return typeNameWithExtension.substring(0, extensionOffset); } /** - * Sets the type name input field's text to the given value. Method doesn't update - * the model. - * + * Sets the type name input field's text to the given value. Method doesn't update the model. * @param name the new type name - * @param canBeModified if true the type name field is - * editable; otherwise it is read-only. + * @param canBeModified if true the type name field is editable; otherwise it is read-only. */ public void setTypeName(String name, boolean canBeModified) { fTypeNameDialogField.setText(name); @@ -1543,37 +1698,36 @@ public void setTypeName(String name, boolean canBeModified) { /** * Returns the selected modifiers. - * * @return the selected modifiers * @see Flags */ public int getModifiers() { - int mdf= 0; + int mdf = 0; if (fAccMdfButtons.isSelected(PUBLIC_INDEX)) { - mdf+= F_PUBLIC; + mdf += F_PUBLIC; } else if (fAccMdfButtons.isSelected(PRIVATE_INDEX)) { - mdf+= F_PRIVATE; + mdf += F_PRIVATE; } else if (fAccMdfButtons.isSelected(PROTECTED_INDEX)) { - mdf+= F_PROTECTED; + mdf += F_PROTECTED; } if (fOtherMdfButtons.isSelected(ABSTRACT_INDEX)) { - mdf+= F_ABSTRACT; + mdf += F_ABSTRACT; } if (fOtherMdfButtons.isSelected(FINAL_INDEX)) { - mdf+= F_FINAL; + mdf += F_FINAL; } if (fOtherMdfButtons.isSelected(STATIC_INDEX)) { - mdf+= F_STATIC; + mdf += F_STATIC; } if (fSealedMdfButtons != null) { if (fSealedMdfButtons.isSelected(SEALED_FINAL_INDEX)) { - mdf+= F_FINAL; + mdf += F_FINAL; } if (fSealedMdfButtons.isSelected(NON_SEALED_INDEX)) { - mdf+= F_NON_SEALED; + mdf += F_NON_SEALED; } if (fSealedMdfButtons.isSelected(SEALED_INDEX)) { - mdf+= F_SEALED; + mdf += F_SEALED; } } return mdf; @@ -1581,12 +1735,10 @@ public int getModifiers() { /** * Sets the modifiers. - * * @param modifiers F_PUBLIC, F_PRIVATE, * F_PROTECTED, F_ABSTRACT, F_FINAL * or F_STATIC or a valid combination. - * @param canBeModified if true the modifier fields are - * editable; otherwise they are read-only + * @param canBeModified if true the modifier fields are editable; otherwise they are read-only * @see Flags */ public void setModifiers(int modifiers, boolean canBeModified) { @@ -1603,10 +1755,11 @@ public void setModifiers(int modifiers, boolean canBeModified) { fOtherMdfButtons.setSelection(ABSTRACT_INDEX, true); } if (Flags.isFinal(modifiers)) { - if (fOtherMdfButtons.isEnabled(FINAL_INDEX)) + if (fOtherMdfButtons.isEnabled(FINAL_INDEX)) { fOtherMdfButtons.setSelection(FINAL_INDEX, true); - else if (fSealedMdfButtons != null) + } else if (fSealedMdfButtons != null) { fSealedMdfButtons.setSelection(SEALED_FINAL_INDEX, true); + } } if (Flags.isStatic(modifiers)) { fOtherMdfButtons.setSelection(STATIC_INDEX, true); @@ -1618,7 +1771,7 @@ else if (fSealedMdfButtons != null) if (Flags.isNonSealed(modifiers)) { fSealedMdfButtons.setSelection(NON_SEALED_INDEX, true); } - fSealedModifierStatus= sealedModifiersChanged(); + fSealedModifierStatus = sealedModifiersChanged(); } fAccMdfButtons.setEnabled(canBeModified); @@ -1627,22 +1780,29 @@ else if (fSealedMdfButtons != null) /** * Returns the content of the superclass input field. - * * @return the superclass name */ public String getSuperClass() { return fSuperClassDialogField.getText(); } + /** + * Sets the super class. + * @param type Super class + */ private void setSuperClass(IType type) { if (type != null) { - fSuperClass= type; - fResetSuperClass= false; + fSuperClass = type; + fResetSuperClass = false; fSuperClassDialogField.setText(SuperInterfaceSelectionDialog.getNameWithTypeParameters(type)); - fResetSuperClass= true; + fResetSuperClass = true; } } + /** + * Sets the enclosing type. + * @param type Enclosing type + */ private void setEnclosingType(IType type) { if (type != null) { fEnclosingTypeDialogField.setText(type.getFullyQualifiedName('.')); @@ -1651,10 +1811,8 @@ private void setEnclosingType(IType type) { /** * Sets the super class name. - * * @param name the new superclass name - * @param canBeModified if true the superclass name field is - * editable; otherwise it is read-only. + * @param canBeModified if true the superclass name field is editable; otherwise it is read-only. */ public void setSuperClass(String name, boolean canBeModified) { fSuperClassDialogField.setText(name); @@ -1663,84 +1821,73 @@ public void setSuperClass(String name, boolean canBeModified) { /** * Sets the super class name. - * * @param type the binding of superclass - * @param canBeModified if true the superclass name field is editable; - * otherwise it is read-only. + * @param canBeModified if true the superclass name field is editable; otherwise it is read-only. * @since 3.25 */ public void setSuperClass(ITypeBinding type, boolean canBeModified) { - fSuperClass= null; + fSuperClass = null; if (type != null) { - IJavaElement jElem= type.getJavaElement(); - if (jElem instanceof IType) { - fSuperClass= (IType) jElem; + IJavaElement jElem = type.getJavaElement(); + if (jElem instanceof IType ty) { + fSuperClass = ty; } - this.fResetSuperClass= false; + this.fResetSuperClass = false; setSuperClass(type.getQualifiedName(), canBeModified); - this.fResetSuperClass= true; + this.fResetSuperClass = true; } - fSuperClassStatus= superClassChanged(); + fSuperClassStatus = superClassChanged(); } /** * Returns the chosen super interfaces. - * * @return a list of chosen super interfaces. The list's elements * are of type String */ public List getSuperInterfaces() { - List interfaces= fSuperInterfacesDialogField.getElements(); - ArrayList result= new ArrayList<>(interfaces.size()); - for (InterfaceWrapper wrapper : interfaces) { - result.add(wrapper.getInterfaceName()); - } - return result; + return fSuperInterfacesDialogField.getElements().stream() + .map(InterfaceWrapper::getInterfaceName) + .collect(Collectors.toList()); } /** * Sets the super interfaces. - * * @param interfacesNames a list of super interface. The method requires that * the list's elements are of type String - * @param canBeModified if true the super interface field is - * editable; otherwise it is read-only. + * @param canBeModified if true the super interface field is editable; otherwise it is read-only. */ public void setSuperInterfaces(List interfacesNames, boolean canBeModified) { - ArrayList interfaces= new ArrayList<>(interfacesNames.size()); - for (String string : interfacesNames) { - interfaces.add(new InterfaceWrapper(string)); - } + List interfaces = interfacesNames.stream() + .map(InterfaceWrapper::new) + .collect(Collectors.toList()); fSuperInterfacesDialogField.setElements(interfaces); fSuperInterfacesDialogField.setEnabled(canBeModified); } /** * Sets the super interfaces. - * * @param interfaceBindings a list of super interface bindings. The method requires that * the list's elements are of type ITypeBinding - * @param canBeModified if true the super interface field is - * editable; otherwise it is read-only. + * @param canBeModified if true the super interface field is editable; otherwise it is read-only. * @since 3.25 */ public void setSuperInterfacesList(List interfaceBindings, boolean canBeModified) { - ArrayList interfaces= new ArrayList<>(interfaceBindings.size()); + ArrayList interfaces = new ArrayList<>(interfaceBindings.size()); for (ITypeBinding typeBinding : interfaceBindings) { - IJavaElement jElem= typeBinding.getJavaElement(); - if (jElem instanceof IType) - interfaces.add(new InterfaceWrapper(typeBinding.getQualifiedName(), (IType) jElem)); - else + IJavaElement jElem = typeBinding.getJavaElement(); + if (jElem instanceof IType ty) { + interfaces.add(new InterfaceWrapper(typeBinding.getQualifiedName(), ty)); + } else { interfaces.add(new InterfaceWrapper(typeBinding.getQualifiedName())); + } } fSuperInterfacesDialogField.setElements(interfaces); fSuperInterfacesDialogField.setEnabled(canBeModified); - fSuperInterfacesStatus= superInterfacesChanged(); + fSuperInterfacesStatus = superInterfacesChanged(); } /** * Adds a super interface to the end of the list and selects it if it is not in the list yet. - * * @param superInterface the fully qualified type name of the interface. * @return returns trueif the interfaces has been added, false * if the interface already is in the list. @@ -1752,7 +1899,6 @@ public boolean addSuperInterface(String superInterface) { /** * Adds a super interface to the end of the list and selects it if it is not in the list yet. - * * @param superInterface the fully qualified type name of the interface. * @param type IType java element of the interface. * @return returns trueif the interfaces has been added, false @@ -1763,15 +1909,12 @@ public boolean addSuperInterface(String superInterface, IType type) { return fSuperInterfacesDialogField.addElement(new InterfaceWrapper(superInterface, type)); } - /** * Sets 'Add comment' checkbox. The value set will only be used when creating source when * the comment control is enabled (see {@link #enableCommentControl(boolean)} - * * @param doAddComments if true, comments are added. - * @param canBeModified if true check box is - * editable; otherwise it is read-only. - * @since 3.1 + * @param canBeModified if true check box is editable; otherwise it is read-only. + * @since 3.1 */ public void setAddComments(boolean doAddComments, boolean canBeModified) { fAddCommentButton.setSelection(doAddComments); @@ -1781,20 +1924,17 @@ public void setAddComments(boolean doAddComments, boolean canBeModified) { /** * Sets to use the 'Add comment' checkbox value. Clients that use the 'Add comment' checkbox * additionally have to enable the control. This has been added for backwards compatibility. - * * @param useAddCommentValue if true, - * @since 3.1 + * @since 3.1 */ public void enableCommentControl(boolean useAddCommentValue) { - fUseAddCommentButtonValue= useAddCommentValue; + fUseAddCommentButtonValue = useAddCommentValue; } - /** * Returns if comments are added. This method can be overridden by clients. * The selection of the comment control is taken if enabled (see {@link #enableCommentControl(boolean)}, otherwise * the settings as specified in the preferences is used. - * * @return Returns true if comments can be added * @since 3.1 */ @@ -1806,64 +1946,71 @@ public boolean isAddComments() { } /** - * Returns the resource handle that corresponds to the compilation unit to was or - * will be created or modified. - * @return A resource or null if the page contains illegal values. + * Returns the resource handle that corresponds to the compilation unit to was or will be created or modified. + * @return A resource or null if the page contains illegal values * @since 3.0 */ public IResource getModifiedResource() { - IType enclosing= getEnclosingType(); + IType enclosing = getEnclosingType(); if (enclosing != null) { return enclosing.getResource(); } - IPackageFragment pack= getPackageFragment(); - if (pack != null) { - String cuName= getCompilationUnitName(getTypeNameWithoutParameters()); - return pack.getCompilationUnit(cuName).getResource(); - } - return null; + IPackageFragment pack = getPackageFragment(); + return pack == null + ? null + // We return only the first of the (maybe many) modified resources + : splitTypeNames(fTypeNameDialogField.getText()).stream() + .findFirst() + .map(TypeNameVariants::nameWithoutParams) + .map(this::getCompilationUnitName) + .map(cuName -> pack.getCompilationUnit(cuName)) + .map(ICompilationUnit::getResource) + .orElse(null); } // ----------- validation ---------- - /* + /** + * {@inheritDoc} * @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#containerChanged() */ @Override protected IStatus containerChanged() { - IStatus status= super.containerChanged(); - IPackageFragmentRoot root= getPackageFragmentRoot(); + IStatus status = super.containerChanged(); + IPackageFragmentRoot root = getPackageFragmentRoot(); if ((fTypeKind == ANNOTATION_TYPE || fTypeKind == ENUM_TYPE) && !status.matches(IStatus.ERROR)) { - if (root != null && !JavaModelUtil.is50OrHigher(root.getJavaProject())) { - // error as createType will fail otherwise (bug 96928) - return new StatusInfo(IStatus.ERROR, Messages.format(NewWizardMessages.NewTypeWizardPage_warning_NotJDKCompliant, BasicElementLabels.getJavaElementName(root.getJavaProject().getElementName()))); - } - if (root != null && fTypeKind == ENUM_TYPE) { - try { - // if findType(...) == null then Enum is unavailable - if (findType(root.getJavaProject(), "java.lang.Enum") == null) //$NON-NLS-1$ - return new StatusInfo(IStatus.WARNING, NewWizardMessages.NewTypeWizardPage_warning_EnumClassNotFound); - } catch (JavaModelException e) { - JavaPlugin.log(e); - } - } - } + if (root != null && !JavaModelUtil.is50OrHigher(root.getJavaProject())) { + // error as createType will fail otherwise (bug 96928) + return new StatusInfo(IStatus.ERROR, Messages.format(NewWizardMessages.NewTypeWizardPage_warning_NotJDKCompliant, BasicElementLabels.getJavaElementName(root.getJavaProject().getElementName()))); + } + if (root != null && fTypeKind == ENUM_TYPE) { + try { + // if findType(...) == null then Enum is unavailable + if (findType(root.getJavaProject(), "java.lang.Enum") == null) { //$NON-NLS-1$ + return new StatusInfo(IStatus.WARNING, NewWizardMessages.NewTypeWizardPage_warning_EnumClassNotFound); + } + } catch (JavaModelException e) { + JavaPlugin.log(e); + } + } + } if ((fTypeKind == RECORD_TYPE) && !status.matches(IStatus.ERROR)) { - if (root != null) { - if (!JavaModelUtil.is16OrHigher(root.getJavaProject())) { - return new StatusInfo(IStatus.ERROR, Messages.format(NewWizardMessages.NewTypeWizardPage_warning_NotJDKCompliant2, new String[] {BasicElementLabels.getJavaElementName(root.getJavaProject().getElementName()), "16" })); //$NON-NLS-1$ - } - try { - // if findType(...) == null then Record is unavailable - if (findType(root.getJavaProject(), "java.lang.Record") == null) //$NON-NLS-1$ - return new StatusInfo(IStatus.WARNING, NewWizardMessages.NewTypeWizardPage_warning_RecordClassNotFound); - } catch (JavaModelException e) { - JavaPlugin.log(e); - } - } else { - return new StatusInfo(IStatus.WARNING, NewWizardMessages.NewTypeWizardPage_warning_RecordClassNotFound); - } - } + if (root != null) { + if (!JavaModelUtil.is16OrHigher(root.getJavaProject())) { + return new StatusInfo(IStatus.ERROR, Messages.format(NewWizardMessages.NewTypeWizardPage_warning_NotJDKCompliant2, new String[] {BasicElementLabels.getJavaElementName(root.getJavaProject().getElementName()), "16" })); //$NON-NLS-1$ + } + try { + // if findType(...) == null then Record is unavailable + if (findType(root.getJavaProject(), "java.lang.Record") == null) { //$NON-NLS-1$ + return new StatusInfo(IStatus.WARNING, NewWizardMessages.NewTypeWizardPage_warning_RecordClassNotFound); + } + } catch (JavaModelException e) { + JavaPlugin.log(e); + } + } else { + return new StatusInfo(IStatus.WARNING, NewWizardMessages.NewTypeWizardPage_warning_RecordClassNotFound); + } + } fCurrPackageCompletionProcessor.setPackageFragmentRoot(root); if (root != null) { @@ -1873,30 +2020,28 @@ protected IStatus containerChanged() { } /** - * A hook method that gets called when the package field has changed. The method - * validates the package name and returns the status of the validation. The validation - * also updates the package fragment model. + * A hook method that gets called when the package field has changed. The method validates the package name and + * returns the status of the validation. The validation also updates the package fragment model. *

* Subclasses may extend this method to perform their own validation. *

- * * @return the status of the validation */ protected IStatus packageChanged() { - StatusInfo status= new StatusInfo(); - IPackageFragmentRoot root= getPackageFragmentRoot(); + StatusInfo status = new StatusInfo(); + IPackageFragmentRoot root = getPackageFragmentRoot(); fPackageDialogField.enableButton(root != null); + IJavaProject project = root != null ? root.getJavaProject() : null; + String packName = getPackageText(); - IJavaProject project= root != null ? root.getJavaProject() : null; - - String packName= getPackageText(); - if (packName.length() > 0) { - IStatus val= validatePackageName(packName, project); + if (!packName.isEmpty()) { + IStatus val = validatePackageName(packName, project); if (val.getSeverity() == IStatus.ERROR) { - status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidPackageName, val.getMessage())); - return status; + return status.withError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidPackageName, + val.getMessage())); } else if (val.getSeverity() == IStatus.WARNING) { - status.setWarning(Messages.format(NewWizardMessages.NewTypeWizardPage_warning_DiscouragedPackageName, val.getMessage())); + status.setWarning(Messages.format(NewWizardMessages.NewTypeWizardPage_warning_DiscouragedPackageName, + val.getMessage())); // continue } } else { @@ -1912,17 +2057,16 @@ protected IStatus packageChanged() { } if (project != null && root != null) { - if (project.exists() && packName.length() > 0) { + if (project.exists() && !packName.isEmpty()) { try { - IPath rootPath= root.getPath(); - IPath outputPath= project.getOutputLocation(); + IPath rootPath = root.getPath(); + IPath outputPath = project.getOutputLocation(); if (rootPath.isPrefixOf(outputPath) && !rootPath.equals(outputPath)) { // if the bin folder is inside of our root, don't allow to name a package // like the bin folder - IPath packagePath= rootPath.append(packName.replace('.', '/')); + IPath packagePath = rootPath.append(packName.replace('.', '/')); if (outputPath.isPrefixOf(packagePath)) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_ClashOutputLocation); - return status; + return status.withError(NewWizardMessages.NewTypeWizardPage_error_ClashOutputLocation); } } } catch (JavaModelException e) { @@ -1931,16 +2075,14 @@ protected IStatus packageChanged() { } } - fCurrPackage= root.getPackageFragment(packName); - IResource resource= fCurrPackage.getResource(); - if (resource != null){ - if (resource.isVirtual()){ - status.setError(NewWizardMessages.NewTypeWizardPage_error_PackageIsVirtual); - return status; + fCurrPackage = root.getPackageFragment(packName); + IResource resource = fCurrPackage.getResource(); + if (resource != null) { + if (resource.isVirtual()) { + return status.withError(NewWizardMessages.NewTypeWizardPage_error_PackageIsVirtual); } if (!ResourcesPlugin.getWorkspace().validateFiltered(resource).isOK()) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_PackageNameFiltered); - return status; + return status.withError(NewWizardMessages.NewTypeWizardPage_error_PackageNameFiltered); } } } else { @@ -1949,220 +2091,241 @@ protected IStatus packageChanged() { return status; } - /* + /** * Updates the 'default' label next to the package field. */ private void updatePackageStatusLabel() { - String packName= getPackageText(); - - if (packName.length() == 0) { - fPackageDialogField.setStatus(NewWizardMessages.NewTypeWizardPage_default); - } else { - fPackageDialogField.setStatus(""); //$NON-NLS-1$ - } + String msg = getPackageText().isEmpty() ? NewWizardMessages.NewTypeWizardPage_default : ""; //$NON-NLS-1$ + fPackageDialogField.setStatus(msg); } - /* + /** * Updates the enable state of buttons related to the enclosing type selection checkbox. */ private void updateEnableState() { - boolean enclosing= isEnclosingTypeSelected(); + boolean enclosing = isEnclosingTypeSelected(); fPackageDialogField.setEnabled(fCanModifyPackage && !enclosing); fEnclosingTypeDialogField.setEnabled(fCanModifyEnclosingType && enclosing); if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) { - fOtherMdfButtons.enableSelectionButton(ABSTRACT_INDEX, enclosing); - fOtherMdfButtons.enableSelectionButton(ENUM_ANNOT_STATIC_INDEX, enclosing); + fOtherMdfButtons.enableSelectionButton(ABSTRACT_INDEX, enclosing); + fOtherMdfButtons.enableSelectionButton(ENUM_ANNOT_STATIC_INDEX, enclosing); } } /** * Hook method that gets called when the enclosing type name has changed. The method - * validates the enclosing type and returns the status of the validation. It also updates the - * enclosing type model. + * validates the enclosing type and returns the status of the validation. It also updates the enclosing type model. *

* Subclasses may extend this method to perform their own validation. *

- * * @return the status of the validation */ protected IStatus enclosingTypeChanged() { - StatusInfo status= new StatusInfo(); - fCurrEnclosingType= null; - - IPackageFragmentRoot root= getPackageFragmentRoot(); - + StatusInfo status = new StatusInfo(); + fCurrEnclosingType = null; + IPackageFragmentRoot root = getPackageFragmentRoot(); fEnclosingTypeDialogField.enableButton(root != null); + if (root == null) { - status.setError(""); //$NON-NLS-1$ - return status; + return status.withError(""); //$NON-NLS-1$ } - String enclName= getEnclosingTypeText(); - if (enclName.length() == 0) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeEnterName); - return status; + String enclName = getEnclosingTypeText(); + if (enclName.isEmpty()) { + return status.withError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeEnterName); } try { - IType type= findType(root.getJavaProject(), enclName); + IType type = findType(root.getJavaProject(), enclName); if (type == null) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeNotExists); - return status; + return status.withError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeNotExists); } if (type.getCompilationUnit() == null) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingNotInCU); - return status; + return status.withError(NewWizardMessages.NewTypeWizardPage_error_EnclosingNotInCU); } if (!JavaModelUtil.isEditable(type.getCompilationUnit())) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingNotEditable); - return status; + return status.withError(NewWizardMessages.NewTypeWizardPage_error_EnclosingNotEditable); } - fCurrEnclosingType= type; - IPackageFragmentRoot enclosingRoot= JavaModelUtil.getPackageFragmentRoot(type); + fCurrEnclosingType = type; + IPackageFragmentRoot enclosingRoot = JavaModelUtil.getPackageFragmentRoot(type); if (!enclosingRoot.equals(root)) { status.setWarning(NewWizardMessages.NewTypeWizardPage_warning_EnclosingNotInSourceFolder); } return status; } catch (JavaModelException e) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeNotExists); JavaPlugin.log(e); - return status; + return status.withError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeNotExists); } } + /** + * Finds the type by name. + * @param project Java project + * @param typeName Type name + * @return Type or null + * @throws JavaModelException In case of Java model problem + */ private IType findType(IJavaProject project, String typeName) throws JavaModelException { - if (project.exists()) { - return project.findType(typeName); - } - return null; - } - - private String getTypeNameWithoutParameters() { - return getTypeNameWithoutParameters(getTypeName()); + return project.exists() ? project.findType(typeName) : null; } + /** + * Answers the type name without parameters. + * @param typeNameWithParameters Type name with parameters + * @return Type name without parameters + */ private static String getTypeNameWithoutParameters(String typeNameWithParameters) { - int angleBracketOffset= typeNameWithParameters.indexOf('<'); - if (angleBracketOffset == -1) { - return typeNameWithParameters; - } else { - return typeNameWithParameters.substring(0, angleBracketOffset); - } + int bracketOffset = typeNameWithParameters.indexOf('<'); + return bracketOffset == -1 ? typeNameWithParameters : typeNameWithParameters.substring(0, bracketOffset); } /** - * Hook method that is called when evaluating the name of the compilation unit to create. By default, a file extension - * java is added to the given type name, but implementors can override this behavior. - * + * Hook method that is called when evaluating the name of the compilation unit to create. By default, a file + * extension java is added to the given type name, but implementors can override this behavior. * @param typeName the name of the type to create the compilation unit for. * @return the name of the compilation unit to be created for the given name - * * @since 3.2 */ protected String getCompilationUnitName(String typeName) { return typeName + JavaModelUtil.DEFAULT_CU_SUFFIX; } - /** - * Hook method that gets called when the type name has changed. The method validates the - * type name and returns the status of the validation. + * Hook method that gets called when the type name field has changed. The method validates the + * type name(s) and returns the status of the validation. *

* Subclasses may extend this method to perform their own validation. *

- * - * @return the status of the validation + * @return Status of the validation */ protected IStatus typeNameChanged() { - StatusInfo status= new StatusInfo(); - fCurrType= null; - + StatusInfo status = new StatusInfo(); String typeNameWithExtension = fTypeNameDialogField.getText(); - // must not be empty - if (typeNameWithExtension.length() == 0) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_EnterTypeName); - return status; + // Must not be empty and must contain at least one letter + if (typeNameWithExtension.isEmpty() || !MIN_ONE_LETTER_PATTERN.matcher(typeNameWithExtension).matches()) { + return status.withError(NewWizardMessages.NewTypeWizardPage_error_EnterTypeName); } - if (typeNameWithExtension.endsWith(JavaModelUtil.DEFAULT_CU_SUFFIX)) { + if (typeNameWithExtension.contains(JavaModelUtil.DEFAULT_CU_SUFFIX)) { status.setInfo(NewWizardMessages.NewTypeWizardPage_info_FileExtensionNotRequired); } - String typeNameWithParameters= getTypeName(); + IJavaProject project = getJavaProject(); + IJavaElement container = isEnclosingTypeSelected() ? getEnclosingType() : getPackageFragment(); + + List valResults = splitTypeNames(typeNameWithExtension).stream() + .map(tnv -> validateTypeName(tnv, project, container, status)) + .collect(Collectors.toList()); - String typeName= getTypeNameWithoutParameters(); + valResults.add(status); // Add the status from above + return valResults.stream() + .sorted(Comparator.comparingInt(IStatus::getSeverity)) + .reduce((a, b) -> b) // To get the last element (which has highest severity) + .orElse(status); // The else case cannot happen since we added a status to the list + } + + /** + * Creates type name variants from the given parameter. + * @param typeNameWithExtension Type name with extension (if any) e. g. ".java" + * @param existing Existing type names (without parameters) + * @return Type name variants + */ + private TypeNameVariants createTypeNameVariants(String typeNameWithExtension, Collection existing) { + String typeNameWithParameters = getTypeNameWithoutExtension(typeNameWithExtension); + String typeNameWithoutParameters = getTypeNameWithoutParameters(typeNameWithParameters); + boolean duplicate = !existing.add(typeNameWithoutParameters); + return new TypeNameVariants(typeNameWithParameters, typeNameWithoutParameters, duplicate); + } + + /** + * Creates type name variants by splitting the type names. + * @param typeNamesWithExtension Type names with extension (if any) e. g. ".java" separated by comma. + * @return Type name variants + */ + private List splitTypeNames(String typeNamesWithExtension) { + Collection existing = new HashSet<>(); + // Using semicolon as separator. Can't use comma because of conflict with multiple type arguments like A. + return Arrays.stream(typeNamesWithExtension.split(";")) //$NON-NLS-1$ This is the separator + .map(String::trim) + .filter(str -> !str.isEmpty()) + .sorted() + .map(typeNameWithExtension -> createTypeNameVariants(typeNameWithExtension, existing)) + // We do not reject the duplicates here because they are needed for validation purposes + .collect(Collectors.toList()); + } + + /** + * Validates the type name and returns the status of the validation. + * @param tnv Type name variants + * @param project Java project + * @param container Containing Java element + * @param status Status info + * @return Status of the validation + */ + private IStatus validateTypeName(TypeNameVariants tnv, IJavaProject project, IJavaElement container, + StatusInfo status) { + + if (tnv.duplicate()) { + String name = tnv.nameWithoutParams(); + return status.withError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_DuplicateName, name)); + } + + String typeName = tnv.nameWithoutParams(); if (typeName.indexOf('.') != -1) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_QualifiedName); - return status; + return status.withError(NewWizardMessages.NewTypeWizardPage_error_QualifiedName); } - IJavaProject project= getJavaProject(); - IStatus val= validateJavaTypeName(typeName, project); + IStatus val = validateJavaTypeName(typeName, project); + String msg = val.getMessage(); if (val.getSeverity() == IStatus.ERROR) { - status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidTypeName, val.getMessage())); - return status; + return status.withError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidTypeName, msg)); } else if (val.getSeverity() == IStatus.WARNING) { - status.setWarning(Messages.format(NewWizardMessages.NewTypeWizardPage_warning_TypeNameDiscouraged, val.getMessage())); + status.setWarning(Messages.format(NewWizardMessages.NewTypeWizardPage_warning_TypeNameDiscouraged, msg)); // continue checking } // must not exist - if (!isEnclosingTypeSelected()) { - IPackageFragment pack= getPackageFragment(); - if (pack != null) { - ICompilationUnit cu= pack.getCompilationUnit(getCompilationUnitName(typeName)); - fCurrType= cu.getType(typeName); - IResource resource= cu.getResource(); + if (isEnclosingTypeSelected() && container instanceof IType type && type.getType(typeName).exists()) { + return status.withError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExists); + } else if (container instanceof IPackageFragment pack) { + ICompilationUnit cu = pack.getCompilationUnit(getCompilationUnitName(typeName)); + IResource resource = cu.getResource(); - if (resource.exists()) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExists); - return status; - } - if (!ResourcesPlugin.getWorkspace().validateFiltered(resource).isOK()) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameFiltered); - return status; - } - URI location= resource.getLocationURI(); - if (location != null) { - try { - IFileStore store= EFS.getStore(location); - if (store.fetchInfo().exists()) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExistsDifferentCase); - return status; - } - } catch (CoreException e) { - status.setError(Messages.format( - NewWizardMessages.NewTypeWizardPage_error_uri_location_unkown, - BasicElementLabels.getURLPart(Resources.getLocationString(resource)))); - } - } + if (resource.exists()) { + return status.withError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExists); } - } else { - IType type= getEnclosingType(); - if (type != null) { - fCurrType= type.getType(typeName); - if (fCurrType.exists()) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExists); - return status; + if (!ResourcesPlugin.getWorkspace().validateFiltered(resource).isOK()) { + return status.withError(NewWizardMessages.NewTypeWizardPage_error_TypeNameFiltered); + } + URI location = resource.getLocationURI(); + if (location != null) { + try { + if (EFS.getStore(location).fetchInfo().exists()) { + return status.withError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExistsDifferentCase); + } + } catch (CoreException e) { + status.setError(Messages.format( + NewWizardMessages.NewTypeWizardPage_error_uri_location_unkown, + BasicElementLabels.getURLPart(Resources.getLocationString(resource)))); } } } + String typeNameWithParameters = tnv.nameWithParams(); if (!typeNameWithParameters.equals(typeName) && project != null) { if (!JavaModelUtil.is50OrHigher(project)) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeParameters); - return status; + return status.withError(NewWizardMessages.NewTypeWizardPage_error_TypeParameters); } - String typeDeclaration= "class " + typeNameWithParameters + " {}"; //$NON-NLS-1$//$NON-NLS-2$ - ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); + String typeDeclaration = String.format("class %s {}", typeNameWithParameters); //$NON-NLS-1$ + ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); parser.setSource(typeDeclaration.toCharArray()); parser.setProject(project); - CompilationUnit compilationUnit= (CompilationUnit) parser.createAST(null); - IProblem[] problems= compilationUnit.getProblems(); + CompilationUnit compilationUnit = (CompilationUnit) parser.createAST(null); + IProblem[] problems = compilationUnit.getProblems(); if (problems.length > 0) { - status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidTypeName, problems[0].getMessage())); - return status; + return status.withError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidTypeName, + problems[0].getMessage())); } } return status; @@ -2174,32 +2337,27 @@ protected IStatus typeNameChanged() { *

* Subclasses may extend this method to perform their own validation. *

- * * @return the status of the validation */ protected IStatus superClassChanged() { - StatusInfo status= new StatusInfo(); - IPackageFragmentRoot root= getPackageFragmentRoot(); + StatusInfo status = new StatusInfo(); + IPackageFragmentRoot root = getPackageFragmentRoot(); fSuperClassDialogField.enableButton(root != null); + fSuperClassStubTypeContext = null; + String sclassName = getSuperClass(); - fSuperClassStubTypeContext= null; - - String sclassName= getSuperClass(); - - if (sclassName.length() == 0) { + if (sclassName.isEmpty()) { // accept the empty field (stands for java.lang.Object) return status; } if (fSuperClass != null) { try { if (fSuperClass.isRecord()) { - status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidSuperClassRecord, BasicElementLabels.getJavaElementName(sclassName))); - return status; + return status.withError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidSuperClassRecord, BasicElementLabels.getJavaElementName(sclassName))); } else { - int flags= fSuperClass.getFlags(); + int flags = fSuperClass.getFlags(); if (Flags.isFinal(flags)) { - status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidFinalSuperClass, BasicElementLabels.getJavaElementName(sclassName))); - return status; + return status.withError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidFinalSuperClass, BasicElementLabels.getJavaElementName(sclassName))); } } } catch (JavaModelException e) { @@ -2207,19 +2365,17 @@ protected IStatus superClassChanged() { } } if (root != null) { - Type type= TypeContextChecker.parseSuperClass(sclassName); + Type type = TypeContextChecker.parseSuperClass(sclassName); if (type == null) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_InvalidSuperClassName); - return status; + return status.withError(NewWizardMessages.NewTypeWizardPage_error_InvalidSuperClassName); } if (type instanceof ParameterizedType && ! JavaModelUtil.is50OrHigher(root.getJavaProject())) { - status.setError(NewWizardMessages.NewTypeWizardPage_error_SuperClassNotParameterized); - return status; + return status.withError(NewWizardMessages.NewTypeWizardPage_error_SuperClassNotParameterized); } } else { status.setError(""); //$NON-NLS-1$ } - fSealedSuperClassStatus= validateSealedSuperClassStatus(); + fSealedSuperClassStatus = validateSealedSuperClassStatus(); enableSealedModifierButtonsIfRequired(); return status; } @@ -2235,9 +2391,9 @@ protected IStatus superClassChanged() { * @since 3.25 */ private IStatus validateSealedSuperClassStatus() { - StatusInfo status= new StatusInfo(); + StatusInfo status = new StatusInfo(); if (fSuperClass != null) { - StatusInfo validStatus= canSuperTypeBeExtended(fSuperClass); + StatusInfo validStatus = canSuperTypeBeExtended(fSuperClass); if (validStatus.isError()) { return validStatus; } @@ -2245,6 +2401,9 @@ private IStatus validateSealedSuperClassStatus() { return status; } + /** + * Enables sealed modifier buttons if required. + */ private void enableSealedModifierButtonsIfRequired() { if (fSealedMdfButtons != null) { if (fIsSealedSupported) { @@ -2260,10 +2419,12 @@ && isSuperTypeSealed()) { } else { setSealedModifiersButtonDefault(); } - } } + /** + * Sets sealed modifier buttons default. + */ private void setSealedModifiersButtonDefault() { if (fSealedMdfButtons != null) { if (isSealedButtonSelected(NON_SEALED_INDEX)) { @@ -2279,13 +2440,18 @@ private void setSealedModifiersButtonDefault() { } } + /** + * Checks if sealed button is selected. + * @param index The index + * @return True if sealed button is selected + */ private boolean isSealedButtonSelected(int index) { - boolean selected= false; + boolean selected = false; if (fSealedMdfButtons != null) { try { - Button button= fSealedMdfButtons.getSelectionButton(index); + Button button = fSealedMdfButtons.getSelectionButton(index); if (button != null && button.isEnabled() && button.getSelection()) { - selected= true; + selected = true; } } catch (NullPointerException npe) { //This will be hit when fSealedMdfButtons is not yet initialized. @@ -2295,100 +2461,106 @@ private boolean isSealedButtonSelected(int index) { return selected; } + /** + * Checks if super type can be extended. + * @param type Super type + * @return True if super type can be extended + */ private StatusInfo canSuperTypeBeExtended(IType type) { - StatusInfo status= new StatusInfo(); - IJavaProject currJavaProject= getJavaProject(); - if (fIsSealedSupported && type != null && currJavaProject != null) { - try { - if (type.isSealed()) { - IJavaProject javaProject= type.getJavaProject(); - if (JavaModelUtil.is9OrHigher(currJavaProject)) { - IModuleDescription projectModule= currJavaProject.getModuleDescription(); - if (projectModule != null - && !projectModule.isAutoModule()) { - if (!currJavaProject.equals(javaProject)) { - String msg= NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperClassInDifferentModule; + StatusInfo status = new StatusInfo(); + IJavaProject currJavaProject = getJavaProject(); + if (!fIsSealedSupported || type == null || currJavaProject == null) { + return status; + } + try { + if (type.isSealed()) { + IJavaProject javaProject = type.getJavaProject(); + if (JavaModelUtil.is9OrHigher(currJavaProject)) { + IModuleDescription projectModule = currJavaProject.getModuleDescription(); + if (projectModule != null && !projectModule.isAutoModule()) { + if (!currJavaProject.equals(javaProject)) { + String msg = NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperClassInDifferentModule; + switch (fTypeKind) { + case INTERFACE_TYPE: + msg = NewWizardMessages.NewTypeWizardPage_error_interface_SealedSuperInterfaceInDifferentModule; + break; + case CLASS_TYPE: + if (type.isInterface()) { + msg = NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperInterfaceInDifferentModule; + } + break; + default: + break; + } + status.setError(msg); + } + } else if (fCurrPackage != null) { + IPackageFragment scPkgFrag = type.getPackageFragment(); + if (!fCurrPackage.equals(scPkgFrag)) { + if (currJavaProject.equals(javaProject)) { + String msg = NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperClassInDifferentPackage; switch (fTypeKind) { case INTERFACE_TYPE: - msg= NewWizardMessages.NewTypeWizardPage_error_interface_SealedSuperInterfaceInDifferentModule; + msg = NewWizardMessages.NewTypeWizardPage_error_interface_SealedSuperInterfaceInDifferentPackage; break; case CLASS_TYPE: if (type.isInterface()) { - msg= NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperInterfaceInDifferentModule; + msg = NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperInterfaceInDifferentPackage; } break; default: break; } status.setError(msg); - } - } else if (fCurrPackage != null) { - IPackageFragment scPkgFrag= type.getPackageFragment(); - if (!fCurrPackage.equals(scPkgFrag)) { - if (currJavaProject.equals(javaProject)) { - String msg= NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperClassInDifferentPackage; - switch (fTypeKind) { - case INTERFACE_TYPE: - msg= NewWizardMessages.NewTypeWizardPage_error_interface_SealedSuperInterfaceInDifferentPackage; - break; - case CLASS_TYPE: - if (type.isInterface()) { - msg= NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperInterfaceInDifferentPackage; - } - break; - default: - break; - } - status.setError(msg); - } else { - String msg= NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperClassInDifferentProject; - switch (fTypeKind) { - case INTERFACE_TYPE: - msg= NewWizardMessages.NewTypeWizardPage_error_interface_SealedSuperInterfaceInDifferentProject; - break; - case CLASS_TYPE: - if (type.isInterface()) { - msg= NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperInterfaceInDifferentProject; - } - break; - default: - break; - } - status.setError(msg); + } else { + String msg = NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperClassInDifferentProject; + switch (fTypeKind) { + case INTERFACE_TYPE: + msg = NewWizardMessages.NewTypeWizardPage_error_interface_SealedSuperInterfaceInDifferentProject; + break; + case CLASS_TYPE: + if (type.isInterface()) { + msg = NewWizardMessages.NewTypeWizardPage_error_class_SealedSuperInterfaceInDifferentProject; + } + break; + default: + break; } + status.setError(msg); } } } } - } catch (JavaModelException e) { - // do nothing } + } catch (JavaModelException e) { + // do nothing } return status; } /** - * @return returns if any of the super types is sealed or not + * Checks if any of the super types is sealed or not. + * @return if any of the super types is sealed or not * @since 3.25 */ protected boolean isSuperTypeSealed() { - boolean isSealed= false; + boolean isSealed = false; if (fIsSealedSupported && fSuperClass != null) { try { if (fSuperClass.isSealed()) { - isSealed= true; + isSealed = true; } } catch (JavaModelException e) { // do nothing } } if (!isSealed) { - List interfaces= fSuperInterfacesDialogField.getElements(); + List interfaces = fSuperInterfacesDialogField.getElements(); for (InterfaceWrapper intWrap : interfaces) { try { - IType type= intWrap.getType(); + IType type = intWrap.getType(); if (type != null && type.isSealed()) { - isSealed= true; + isSealed = true; } } catch (JavaModelException e) { //do nothing @@ -2399,24 +2571,28 @@ protected boolean isSuperTypeSealed() { } /** - * @return returns true if the super class is final + * Checks if the super class is final. + * @return true if the super class is final * @since 3.30 */ protected boolean isSuperClassFinal() { try { return fSuperClass != null && Flags.isFinal(fSuperClass.getFlags()); } catch (Exception e) { - // fall through + return false; } - return false; } + /** + * Checks if the super class is sealed. + * @return True if the super class is sealed + */ private boolean isSuperClassSealed() { - boolean isSealed= false; + boolean isSealed = false; if (fIsSealedSupported && fSuperClass != null) { try { if (fSuperClass.isSealed()) { - isSealed= true; + isSealed = true; } } catch (JavaModelException e) { // do nothing @@ -2425,33 +2601,31 @@ private boolean isSuperClassSealed() { return isSealed; } + /** + * Checks if the valid sealed flag is selected. + * @return True if the valid sealed flag is selected + */ private boolean isValidSealedFlagSelected() { - boolean isEnabled= false; - if (fSealedMdfButtons != null) { - if (fSealedMdfButtons.isEnabled(SEALED_INDEX) - && fSealedMdfButtons.isSelected(SEALED_INDEX)) { - isEnabled= true; - } else if (fSealedMdfButtons.isEnabled(NON_SEALED_INDEX) - && fSealedMdfButtons.isSelected(NON_SEALED_INDEX)) { - isEnabled= true; - } else if (fTypeKind != INTERFACE_TYPE - && fSealedMdfButtons.isEnabled(SEALED_FINAL_INDEX) - && fSealedMdfButtons.isSelected(SEALED_FINAL_INDEX)) { - isEnabled= true; - } + if (fSealedMdfButtons == null) { + return false; } - return isEnabled; + return fSealedMdfButtons.isEnabled(SEALED_INDEX) && fSealedMdfButtons.isSelected(SEALED_INDEX) + || fSealedMdfButtons.isEnabled(NON_SEALED_INDEX) && fSealedMdfButtons.isSelected(NON_SEALED_INDEX) + || fTypeKind != INTERFACE_TYPE + && fSealedMdfButtons.isEnabled(SEALED_FINAL_INDEX) + && fSealedMdfButtons.isSelected(SEALED_FINAL_INDEX); } - private StubTypeContext getSuperClassStubTypeContext() { + /** + * Gets the super class stub type context. + * @param typeName Type name + * @return The super class stub type context + */ + private StubTypeContext getSuperClassStubTypeContext(String typeName) { if (fSuperClassStubTypeContext == null) { - String typeName; - if (fCurrType != null) { - typeName= getTypeName(); - } else { - typeName= JavaTypeCompletionProcessor.DUMMY_CLASS_NAME; - } - fSuperClassStubTypeContext= TypeContextChecker.createSuperClassStubTypeContext(typeName, getEnclosingType(), getPackageFragment()); + String ctxTypeName = typeName == null ? JavaTypeCompletionProcessor.DUMMY_CLASS_NAME : typeName; + fSuperClassStubTypeContext = TypeContextChecker.createSuperClassStubTypeContext(ctxTypeName, + getEnclosingType(), getPackageFragment()); } return fSuperClassStubTypeContext; } @@ -2462,31 +2636,28 @@ private StubTypeContext getSuperClassStubTypeContext() { *

* Subclasses may extend this method to perform their own validation. *

- * * @return the status of the validation */ protected IStatus superInterfacesChanged() { - StatusInfo status= new StatusInfo(); + StatusInfo status = new StatusInfo(); - IPackageFragmentRoot root= getPackageFragmentRoot(); + IPackageFragmentRoot root = getPackageFragmentRoot(); fSuperInterfacesDialogField.enableButton(0, root != null); if (root != null) { - List elements= fSuperInterfacesDialogField.getElements(); + List elements = fSuperInterfacesDialogField.getElements(); for (InterfaceWrapper element : elements) { - String intfname= element.getInterfaceName(); - Type type= TypeContextChecker.parseSuperInterface(intfname); + String intfname = element.getInterfaceName(); + Type type = TypeContextChecker.parseSuperInterface(intfname); if (type == null) { - status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidSuperInterfaceName, BasicElementLabels.getJavaElementName(intfname))); - return status; + return status.withError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidSuperInterfaceName, BasicElementLabels.getJavaElementName(intfname))); } if (type instanceof ParameterizedType && ! JavaModelUtil.is50OrHigher(root.getJavaProject())) { - status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_SuperInterfaceNotParameterized, BasicElementLabels.getJavaElementName(intfname))); - return status; + return status.withError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_SuperInterfaceNotParameterized, BasicElementLabels.getJavaElementName(intfname))); } } } - fSealedSuperInterfacesStatus= validateSealedSuperInterfacesStatus(); + fSealedSuperInterfacesStatus = validateSealedSuperInterfacesStatus(); enableSealedModifierButtonsIfRequired(); return status; } @@ -2502,29 +2673,30 @@ protected IStatus superInterfacesChanged() { * @since 3.25 */ protected IStatus validateSealedSuperInterfacesStatus() { - StatusInfo status= new StatusInfo(); - List elements= fSuperInterfacesDialogField.getElements(); + StatusInfo status = new StatusInfo(); + List elements = fSuperInterfacesDialogField.getElements(); for (InterfaceWrapper element : elements) { - IType eType= element.getType(); + IType eType = element.getType(); if (eType != null) { - StatusInfo validStatus= canSuperTypeBeExtended(eType); + StatusInfo validStatus = canSuperTypeBeExtended(eType); if (validStatus.isError()) { - status= validStatus; + status = validStatus; } } } return status; } - private StubTypeContext getSuperInterfacesStubTypeContext() { + /** + * Answers the super interfaces stub type context. + * @param typeName Type name + * @return Super interfaces stub type context + */ + private StubTypeContext getSuperInterfacesStubTypeContext(String typeName) { if (fSuperInterfaceStubTypeContext == null) { - String typeName; - if (fCurrType != null) { - typeName= getTypeName(); - } else { - typeName= JavaTypeCompletionProcessor.DUMMY_CLASS_NAME; - } - fSuperInterfaceStubTypeContext= TypeContextChecker.createSuperInterfaceStubTypeContext(typeName, getEnclosingType(), getPackageFragment()); + String ctxTypeName = typeName == null ? JavaTypeCompletionProcessor.DUMMY_CLASS_NAME : typeName; + fSuperInterfaceStubTypeContext = TypeContextChecker.createSuperInterfaceStubTypeContext(ctxTypeName, + getEnclosingType(), getPackageFragment()); } return fSuperInterfaceStubTypeContext; } @@ -2539,22 +2711,27 @@ private StubTypeContext getSuperInterfacesStubTypeContext() { * @return the status of the validation */ protected IStatus modifiersChanged() { - StatusInfo status= new StatusInfo(); - int modifiers= getModifiers(); + StatusInfo status = new StatusInfo(); + int modifiers = getModifiers(); if (Flags.isFinal(modifiers) && Flags.isAbstract(modifiers)) { status.setError(NewWizardMessages.NewTypeWizardPage_error_ModifiersFinalAndAbstract); } return status; } + /** + * Hook method that gets called when the sealed modifiers have changed. The method validates + * the modifiers and returns the status of the validation. + * @return the status of the validation + */ private IStatus sealedModifiersChanged() { - StatusInfo status= new StatusInfo(); + StatusInfo status = new StatusInfo(); if (isSuperTypeSealed() && !isValidSealedFlagSelected()) { - String msg= NewWizardMessages.NewTypeWizardPage_error_SealedFinalNonSealedClass_extend_superclass_notSelected_message; + String msg = NewWizardMessages.NewTypeWizardPage_error_SealedFinalNonSealedClass_extend_superclass_notSelected_message; if (fTypeKind == INTERFACE_TYPE) { - msg= NewWizardMessages.NewTypeWizardPage_error_SealedFinalNonSealedInterface_extend_superinterface_notSelected_message; + msg = NewWizardMessages.NewTypeWizardPage_error_SealedFinalNonSealedInterface_extend_superinterface_notSelected_message; } else if (!isSuperClassSealed()) { - msg= NewWizardMessages.NewTypeWizardPage_error_SealedFinalNonSealedClass_implement_superinterface_notSelected_message; + msg = NewWizardMessages.NewTypeWizardPage_error_SealedFinalNonSealedClass_implement_superinterface_notSelected_message; } status.setError(msg); } @@ -2565,30 +2742,29 @@ private IStatus sealedModifiersChanged() { /** * Opens a selection dialog that allows to select a package. - * * @return returns the selected package or null if the dialog has been canceled. * The caller typically sets the result to the package input field. *

* Clients can override this method if they want to offer a different dialog. *

- * * @since 3.2 */ protected IPackageFragment choosePackage() { - IPackageFragmentRoot froot= getPackageFragmentRoot(); - IJavaElement[] packages= null; + IPackageFragmentRoot froot = getPackageFragmentRoot(); + IJavaElement[] packages = null; try { if (froot != null && froot.exists()) { - packages= froot.getChildren(); + packages = froot.getChildren(); } } catch (JavaModelException e) { JavaPlugin.log(e); } if (packages == null) { - packages= new IJavaElement[0]; + packages = new IJavaElement[0]; } - ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT)); + JavaElementLabelProvider provider = new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT); + var dialog = new ElementListSelectionDialog(getShell(), provider); dialog.setIgnoreCase(false); dialog.setTitle(NewWizardMessages.NewTypeWizardPage_ChoosePackageDialog_title); dialog.setMessage(NewWizardMessages.NewTypeWizardPage_ChoosePackageDialog_description); @@ -2596,89 +2772,75 @@ protected IPackageFragment choosePackage() { dialog.setElements(packages); dialog.setHelpAvailable(false); - IPackageFragment pack= getPackageFragment(); + IPackageFragment pack = getPackageFragment(); if (pack != null) { dialog.setInitialSelections(pack); } - if (dialog.open() == Window.OK) { - return (IPackageFragment) dialog.getFirstResult(); - } - return null; + return dialog.open() == Window.OK ? (IPackageFragment) dialog.getFirstResult() : null; } /** * Opens a selection dialog that allows to select an enclosing type. - * * @return returns the selected type or null if the dialog has been canceled. * The caller typically sets the result to the enclosing type input field. *

* Clients can override this method if they want to offer a different dialog. *

- * * @since 3.2 */ protected IType chooseEnclosingType() { - IPackageFragmentRoot root= getPackageFragmentRoot(); + IPackageFragmentRoot root = getPackageFragmentRoot(); if (root == null) { return null; } - IJavaSearchScope scope= SearchEngine.createJavaSearchScope(new IJavaElement[] { root }); - - FilteredTypesSelectionDialog dialog= new FilteredTypesSelectionDialog(getShell(), - false, getWizard().getContainer(), scope, IJavaSearchConstants.TYPE); + IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { root }); + IWizardContainer container = getWizard().getContainer(); + var dialog = new FilteredTypesSelectionDialog(getShell(), false, container, scope, IJavaSearchConstants.TYPE); dialog.setTitle(NewWizardMessages.NewTypeWizardPage_ChooseEnclosingTypeDialog_title); dialog.setMessage(NewWizardMessages.NewTypeWizardPage_ChooseEnclosingTypeDialog_description); dialog.setInitialPattern(Signature.getSimpleName(getEnclosingTypeText())); - - if (dialog.open() == Window.OK) { - return (IType) dialog.getFirstResult(); - } - return null; + return dialog.open() == Window.OK ? (IType) dialog.getFirstResult() : null; } /** * Opens a selection dialog that allows to select a super class. - * * @return returns the selected type or null if the dialog has been canceled. * The caller typically sets the result to the super class input field. *

* Clients can override this method if they want to offer a different dialog. *

- * * @since 3.2 */ protected IType chooseSuperClass() { - IJavaProject project= getJavaProject(); + IJavaProject project = getJavaProject(); if (project == null) { return null; } - IJavaElement[] elements= new IJavaElement[] { project }; - IJavaSearchScope scope= SearchEngine.createJavaSearchScope(elements); - - FilteredTypesSelectionDialog dialog= new FilteredTypesSelectionDialog(getShell(), false, - getWizard().getContainer(), scope, IJavaSearchConstants.CLASS); + IJavaElement[] elements = new IJavaElement[] { project }; + IJavaSearchScope scope = SearchEngine.createJavaSearchScope(elements); + IWizardContainer container = getWizard().getContainer(); + var dialog = new FilteredTypesSelectionDialog(getShell(), false, container, scope, IJavaSearchConstants.CLASS); dialog.setTitle(NewWizardMessages.NewTypeWizardPage_SuperClassDialog_title); dialog.setMessage(NewWizardMessages.NewTypeWizardPage_SuperClassDialog_message); dialog.setInitialPattern(getSuperClass()); - - if (dialog.open() == Window.OK) { - return (IType) dialog.getFirstResult(); - } - return null; + return dialog.open() == Window.OK ? (IType) dialog.getFirstResult() : null; } + /** + * Sets the super class type. + */ private void setSuperClassType() { if (this.fResetSuperClass) { - fSuperClass= null; - IJavaProject project= getJavaProject(); + fSuperClass = null; + IJavaProject project = getJavaProject(); if (project == null) { return; } try { - this.fSuperClass= project.findType(getSuperClass()); + this.fSuperClass = project.findType(getSuperClass()); } catch (JavaModelException e) { //do nothing } @@ -2688,172 +2850,119 @@ private void setSuperClassType() { /** * Opens a selection dialog that allows to select the super interfaces. The selected interfaces are * directly added to the wizard page using {@link #addSuperInterface(String)}. - * *

* Clients can override this method if they want to offer a different dialog. *

- * * @since 3.2 */ protected void chooseSuperInterfaces() { - IJavaProject project= getJavaProject(); + IJavaProject project = getJavaProject(); if (project == null) { return; } - SuperInterfaceSelectionDialog dialog= new SuperInterfaceSelectionDialog(getShell(), getWizard().getContainer(), this, project); + var dialog = new SuperInterfaceSelectionDialog(getShell(), getWizard().getContainer(), this, project); dialog.setTitle(getInterfaceDialogTitle()); dialog.setMessage(NewWizardMessages.NewTypeWizardPage_InterfacesDialog_message); dialog.open(); } + /** + * Answers the interface dialog title. + * @return Interface dialog title + */ private String getInterfaceDialogTitle() { - if (fTypeKind == INTERFACE_TYPE) - return NewWizardMessages.NewTypeWizardPage_InterfacesDialog_interface_title; - return NewWizardMessages.NewTypeWizardPage_InterfacesDialog_class_title; + return fTypeKind == INTERFACE_TYPE + ? NewWizardMessages.NewTypeWizardPage_InterfacesDialog_interface_title + : NewWizardMessages.NewTypeWizardPage_InterfacesDialog_class_title; } - // ---- creation ---------------- /** - * Creates the new type using the entered field values. - * - * @param monitor a progress monitor to report progress. - * @throws CoreException Thrown when the creation failed. - * @throws InterruptedException Thrown when the operation was canceled. + * Creates the new type(s) using the entered field values. + * @param monitor Progress monitor to report progress + * @throws CoreException Thrown when the creation failed + * @throws InterruptedException Thrown when the operation was canceled */ public void createType(IProgressMonitor monitor) throws CoreException, InterruptedException { if (monitor == null) { - monitor= new NullProgressMonitor(); + monitor = new NullProgressMonitor(); } - monitor.beginTask(NewWizardMessages.NewTypeWizardPage_operationdesc, 8); + monitor.beginTask(NewWizardMessages.NewTypeWizardPage_operationdesc, 2); + IPackageFragmentRoot root = getPackageFragmentRoot(); + IPackageFragment pack = getPackageFragment(); - IPackageFragmentRoot root= getPackageFragmentRoot(); - IPackageFragment pack= getPackageFragment(); if (pack == null) { - pack= root.getPackageFragment(""); //$NON-NLS-1$ + pack = root.getPackageFragment(""); //$NON-NLS-1$ } if (!pack.exists()) { - String packName= pack.getElementName(); - pack= root.createPackageFragment(packName, true, Progress.subMonitor(monitor, 1)); + String packName = pack.getElementName(); + pack = root.createPackageFragment(packName, true, Progress.subMonitor(monitor, 1)); } else { monitor.worked(1); } - boolean needsSave; - ICompilationUnit connectedCU= null; - try { - String typeName= getTypeNameWithoutParameters(); - - boolean isInnerClass= isEnclosingTypeSelected(); - - IType createdType; - ImportsManager imports; - int indent= 0; - - Set existingImports; - - String lineDelimiter= null; - if (!isInnerClass) { - lineDelimiter= StubUtility.getLineDelimiterUsed(pack.getJavaProject()); - - String cuName= getCompilationUnitName(typeName); - ICompilationUnit parentCU= pack.createCompilationUnit(cuName, "", false, Progress.subMonitor(monitor, 2)); //$NON-NLS-1$ - // create a working copy with a new owner - - needsSave= true; - parentCU.becomeWorkingCopy(Progress.subMonitor(monitor, 1)); // cu is now a (primary) working copy - connectedCU= parentCU; - - IBuffer buffer= parentCU.getBuffer(); + boolean isInnerClass = isEnclosingTypeSelected(); + List tnvs = splitTypeNames(fTypeNameDialogField.getText()); - String simpleTypeStub= constructSimpleTypeStub(); - String cuContent= constructCUContent(parentCU, simpleTypeStub, lineDelimiter); - buffer.setContents(cuContent); + // Following is not done with a stream because of the declared exceptions + List createdTypes = new ArrayList<>(); + for (TypeNameVariants tnv : tnvs) { + createdTypes.add(createType(tnv, isInnerClass, pack, Progress.subMonitor(monitor, 1))); + } + fCreatedTypes = createdTypes; // Set the list of created types + } finally { + monitor.done(); + } + } - CompilationUnit astRoot= createASTForImports(parentCU); - existingImports= getExistingImports(astRoot); + /** + * Creates the new type using the given values. + * @param tnv Type name variants + * @param isInnerClass True if inner class + * @param pack Package fragment + * @param monitor a progress monitor to report progress + * @return Created type + * @throws CoreException Thrown when the creation failed + * @throws InterruptedException Thrown when the operation was canceled + */ + private IType createType(TypeNameVariants tnv, boolean isInnerClass, IPackageFragment pack, + IProgressMonitor monitor) throws CoreException, InterruptedException { - imports= new ImportsManager(astRoot); - // add an import that will be removed again. Having this import solves 14661 - imports.addImport(JavaModelUtil.concatenateName(pack.getElementName(), typeName)); + ICompilationUnit connectedCU = null; + IType createdType = null; - String typeContent= constructTypeStub(parentCU, imports, lineDelimiter); + try { + String typeName = tnv.nameWithoutParams(); - int index= cuContent.lastIndexOf(simpleTypeStub); - if (index == -1) { - AbstractTypeDeclaration typeNode= (AbstractTypeDeclaration) astRoot.types().get(0); - int start= ((ASTNode) typeNode.modifiers().get(0)).getStartPosition(); - int end= typeNode.getStartPosition() + typeNode.getLength(); - buffer.replace(start, end - start, typeContent); - } else { - buffer.replace(index, simpleTypeStub.length(), typeContent); + IType currType = null; // Handle to the type to be created (does usually not exist, can be null) + if (isInnerClass) { + IType type = getEnclosingType(); + if (type != null) { + currType = type.getType(typeName); } - - createdType= parentCU.getType(typeName); } else { - IType enclosingType= getEnclosingType(); - - ICompilationUnit parentCU= enclosingType.getCompilationUnit(); - - needsSave= !parentCU.isWorkingCopy(); - parentCU.becomeWorkingCopy(Progress.subMonitor(monitor, 1)); // cu is now for sure (primary) a working copy - connectedCU= parentCU; - - CompilationUnit astRoot= createASTForImports(parentCU); - imports= new ImportsManager(astRoot); - existingImports= getExistingImports(astRoot); - - - // add imports that will be removed again. Having the imports solves 14661 - for (IType topLevelType : parentCU.getTypes()) { - imports.addImport(topLevelType.getFullyQualifiedName('.')); - } - - lineDelimiter= StubUtility.getLineDelimiterUsed(enclosingType); - StringBuilder content= new StringBuilder(); - - String comment= getTypeComment(parentCU, lineDelimiter); - if (comment != null) { - content.append(comment); - content.append(lineDelimiter); - } - - content.append(constructTypeStub(parentCU, imports, lineDelimiter)); - IJavaElement sibling= null; - if (enclosingType.isEnum()) { - IField[] fields = enclosingType.getFields(); - if (fields.length > 0) { - for (IField field : fields) { - if (!field.isEnumConstant()) { - sibling = field; - break; - } - } - } - } else { - IJavaElement[] elems= enclosingType.getChildren(); - sibling = elems.length > 0 ? elems[0] : null; - } + ICompilationUnit cu = pack.getCompilationUnit(getCompilationUnitName(typeName)); + currType = cu.getType(typeName); + } - createdType= enclosingType.createType(content.toString(), sibling, false, Progress.subMonitor(monitor, 2)); + TypeCreationResult tcr = isInnerClass + ? createInnerType(currType, tnv, monitor) + : createNonInnerType(currType, tnv, pack, monitor); - indent= StubUtility.getIndentUsed(enclosingType) + 1; - } if (monitor.isCanceled()) { throw new InterruptedException(); } // add imports for superclass/interfaces, so types can be resolved correctly - - ICompilationUnit cu= createdType.getCompilationUnit(); - + createdType = tcr.createdType(); + ICompilationUnit cu = createdType.getCompilationUnit(); + ImportsManager imports = tcr.imports(); imports.create(false, Progress.subMonitor(monitor, 1)); - JavaModelUtil.reconcile(cu); if (monitor.isCanceled()) { @@ -2861,95 +2970,209 @@ public void createType(IProgressMonitor monitor) throws CoreException, Interrupt } // set up again - CompilationUnit astRoot= createASTForImports(imports.getCompilationUnit()); - imports= new ImportsManager(astRoot); + CompilationUnit astRoot = createASTForImports(imports.getCompilationUnit()); + imports = new ImportsManager(astRoot); createTypeMembers(createdType, imports, Progress.subMonitor(monitor, 1)); // add imports imports.create(false, Progress.subMonitor(monitor, 1)); - - removeUnusedImports(cu, existingImports, false); - + removeUnusedImports(cu, tcr.existingImports(), false); JavaModelUtil.reconcile(cu); - ISourceRange range= createdType.getSourceRange(); + ISourceRange range = createdType.getSourceRange(); + int indent = isInnerClass ? StubUtility.getIndentUsed(getEnclosingType()) + 1 : 0; + IBuffer buf = cu.getBuffer(); + String originalContent = buf.getText(range.getOffset(), range.getLength()); + String lineDelimiter = tcr.lineDelimiter(); - IBuffer buf= cu.getBuffer(); - String originalContent= buf.getText(range.getOffset(), range.getLength()); + String formattedContent = CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, originalContent, + indent, lineDelimiter, FormatterProfileManager.getProjectSettings(pack.getJavaProject())); - String formattedContent= CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, originalContent, indent, lineDelimiter, - FormatterProfileManager.getProjectSettings(pack.getJavaProject())); - formattedContent= Strings.trimLeadingTabsAndSpaces(formattedContent); + formattedContent = Strings.trimLeadingTabsAndSpaces(formattedContent); buf.replace(range.getOffset(), range.getLength(), formattedContent); if (!isInnerClass) { - String fileComment= getFileComment(cu); - if (fileComment != null && fileComment.length() > 0) { + String fileComment = getFileComment(cu); + if (fileComment != null && !fileComment.isEmpty()) { buf.replace(0, 0, fileComment + lineDelimiter); } } - fCreatedType= createdType; - if (needsSave) { + if (tcr.needsSave()) { cu.commitWorkingCopy(true, Progress.subMonitor(monitor, 1)); } else { monitor.worked(1); } - updateSealedSuperTypes(); - + updateSealedSuperTypes(createdType, typeName); + connectedCU = tcr.connectedCU(); } finally { if (connectedCU != null) { connectedCU.discardWorkingCopy(); } - monitor.done(); } + return createdType; + } + + /** + * Creates an inner type. + * @param currentType Current type + * @param tnv Type name variants + * @param monitor Progress monitor + * @return Type creation result + * @throws CoreException Thrown when the creation failed + */ + private TypeCreationResult createInnerType(IType currentType, TypeNameVariants tnv, IProgressMonitor monitor) + throws CoreException { + + IType encType = getEnclosingType(); + ICompilationUnit parentCU = encType.getCompilationUnit(); + final boolean needsSave = !parentCU.isWorkingCopy(); // Must be before next line, do not move this further down + parentCU.becomeWorkingCopy(Progress.subMonitor(monitor, 1)); // cu is now for sure (primary) a working copy + + CompilationUnit astRoot = createASTForImports(parentCU); + ImportsManager imports = new ImportsManager(astRoot); + + // add imports that will be removed again. Having the imports solves 14661 + for (IType topLevelType : parentCU.getTypes()) { + imports.addImport(topLevelType.getFullyQualifiedName('.')); + } + + String lineDelimiter = StubUtility.getLineDelimiterUsed(encType); + StringBuilder content = new StringBuilder(); + + String comment = getTypeComment(tnv.nameWithoutParams, parentCU, lineDelimiter); + if (comment != null) { + content.append(comment); + content.append(lineDelimiter); + } + + content.append(constructTypeStub(currentType, tnv, parentCU, imports, lineDelimiter)); + IJavaElement sibling = null; + if (encType.isEnum()) { + for (IField field : encType.getFields()) { + if (!field.isEnumConstant()) { + sibling = field; + break; + } + } + } else { + IJavaElement[] elems = encType.getChildren(); + sibling = elems.length > 0 ? elems[0] : null; + } + + IType createdType = encType.createType(content.toString(), sibling, false, Progress.subMonitor(monitor, 2)); + Collection existingImports = getExistingImports(astRoot); + return new TypeCreationResult(createdType, imports, existingImports, parentCU, needsSave, lineDelimiter); + } + + /** + * Creates an inner type. + * @param currentType Current type + * @param tnv Type name variants + * @param pack Package fragment + * @param monitor Progress monitor + * @return Type creation result + * @throws CoreException Thrown when the creation failed + */ + private TypeCreationResult createNonInnerType(IType currentType, TypeNameVariants tnv, IPackageFragment pack, + IProgressMonitor monitor) throws CoreException { + + String lineDelimiter = StubUtility.getLineDelimiterUsed(pack.getJavaProject()); + String cuName = getCompilationUnitName(tnv.nameWithoutParams); + var parentCU = pack.createCompilationUnit(cuName, "", false, Progress.subMonitor(monitor, 2)); //$NON-NLS-1$ + + // create a working copy with a new owner + parentCU.becomeWorkingCopy(Progress.subMonitor(monitor, 1)); // cu is now a (primary) working copy + IBuffer buffer = parentCU.getBuffer(); + String simpleTypeStub = constructSimpleTypeStub(tnv.nameWithoutParams); + String cuContent = constructCUContent(tnv.nameWithoutParams, parentCU, simpleTypeStub, lineDelimiter); + buffer.setContents(cuContent); + + CompilationUnit astRoot = createASTForImports(parentCU); + Collection existingImports = getExistingImports(astRoot); + + ImportsManager imports = new ImportsManager(astRoot); + // add an import that will be removed again. Having this import solves 14661 + imports.addImport(JavaModelUtil.concatenateName(pack.getElementName(), tnv.nameWithoutParams)); + + String typeContent = constructTypeStub(currentType, tnv, parentCU, imports, lineDelimiter); + + int index = cuContent.lastIndexOf(simpleTypeStub); + if (index == -1) { + AbstractTypeDeclaration typeNode = (AbstractTypeDeclaration) astRoot.types().get(0); + int start = ((ASTNode) typeNode.modifiers().get(0)).getStartPosition(); + int end = typeNode.getStartPosition() + typeNode.getLength(); + buffer.replace(start, end - start, typeContent); + } else { + buffer.replace(index, simpleTypeStub.length(), typeContent); + } + + IType createdType = parentCU.getType(tnv.nameWithoutParams); + return new TypeCreationResult(createdType, imports, existingImports, parentCU, true, lineDelimiter); } + /** + * Creates the AST for imports. + * @param cu Compilation unit + * @return AST for imports + */ private CompilationUnit createASTForImports(ICompilationUnit cu) { - ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); + ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); parser.setSource(cu); parser.setResolveBindings(true); parser.setFocalPosition(0); return (CompilationUnit) parser.createAST(null); } - - private Set getExistingImports(CompilationUnit root) { - List imports= root.imports(); - Set res= new HashSet<>(imports.size()); - for (ImportDeclaration import1 : imports) { - res.add(ASTNodes.asString(import1)); - } - return res; + /** + * Gets the existing imports. + * @param root Compilation unit + * @return Existing imports + */ + private Collection getExistingImports(CompilationUnit root) { + List imports = root.imports(); + return imports.stream() + .map(ASTNodes::asString) + .collect(Collectors.toSet()); } - private void removeUnusedImports(ICompilationUnit cu, Set existingImports, boolean needsSave) throws CoreException { - ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); + /** + * Removes unused imports. + * @param cu Compilation unit + * @param existingImports Existing imports + * @param needsSave True if saving required + * @throws CoreException If removing fails + */ + private void removeUnusedImports(ICompilationUnit cu, Collection existingImports, boolean needsSave) + throws CoreException { + + ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); parser.setSource(cu); parser.setResolveBindings(true); - CompilationUnit root= (CompilationUnit) parser.createAST(null); + CompilationUnit root = (CompilationUnit) parser.createAST(null); if (root.getProblems().length == 0) { return; } - List importsDecls= root.imports(); + List importsDecls = root.imports(); if (importsDecls.isEmpty()) { return; } - ImportsManager imports= new ImportsManager(root); - int importsEnd= ASTNodes.getExclusiveEnd(importsDecls.get(importsDecls.size() - 1)); + ImportsManager imports = new ImportsManager(root); + int importsEnd = ASTNodes.getExclusiveEnd(importsDecls.get(importsDecls.size() - 1)); for (IProblem curr : root.getProblems()) { if (curr.getSourceEnd() < importsEnd) { - int id= curr.getID(); - if (id == IProblem.UnusedImport || id == IProblem.NotVisibleType) { // not visible problems hide unused -> remove both - int pos= curr.getSourceStart(); + int id = curr.getID(); + if (id == IProblem.UnusedImport || id == IProblem.NotVisibleType) { + // not visible problems hide unused -> remove both + int pos = curr.getSourceStart(); for (ImportDeclaration decl : importsDecls) { if (decl.getStartPosition() <= pos && pos < decl.getStartPosition() + decl.getLength()) { if (existingImports.isEmpty() || !existingImports.contains(ASTNodes.asString(decl))) { - String name= decl.getName().getFullyQualifiedName(); + String name = decl.getName().getFullyQualifiedName(); if (decl.isOnDemand()) { name += ".*"; //$NON-NLS-1$ } @@ -2971,92 +3194,100 @@ private void removeUnusedImports(ICompilationUnit cu, Set existingImport /** * Uses the New Java file template from the code template page to generate a * compilation unit with the given type content. - * + * @param typeName Type name * @param cu The new created compilation unit - * @param typeContent The content of the type, including signature and type - * body. - * @param lineDelimiter The line delimiter to be used. - * @return String Returns the result of evaluating the new file template - * with the given type content. + * @param typeContent The content of the type, including signature and type body. + * @param lineDelim The line delimiter to be used. + * @return String Returns the result of evaluating the new file template with the given type content. * @throws CoreException when fetching the file comment fails or fetching the content for the - * new compilation unit fails - * @since 2.1 - */ - protected String constructCUContent(ICompilationUnit cu, String typeContent, String lineDelimiter) throws CoreException { - String fileComment= getFileComment(cu, lineDelimiter); - String typeComment= getTypeComment(cu, lineDelimiter); - IPackageFragment pack= (IPackageFragment) cu.getParent(); - String content= CodeGeneration.getCompilationUnitContent(cu, fileComment, typeComment, typeContent, lineDelimiter); + * new compilation unit fails + * @since 3.33 + */ + protected String constructCUContent(String typeName, ICompilationUnit cu, String typeContent, String lineDelim) + throws CoreException { + + String fileComment = getFileComment(cu, lineDelim); + String typeComment = getTypeComment(typeName, cu, lineDelim); + IPackageFragment pack = (IPackageFragment) cu.getParent(); + String content = CodeGeneration.getCompilationUnitContent(cu, fileComment, typeComment, typeContent, lineDelim); if (content != null) { - ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); + ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); parser.setProject(cu.getJavaProject()); parser.setSource(content.toCharArray()); - CompilationUnit unit= (CompilationUnit) parser.createAST(null); + CompilationUnit unit = (CompilationUnit) parser.createAST(null); if ((pack.isDefaultPackage() || unit.getPackage() != null) && !unit.types().isEmpty()) { return content; } } - StringBuilder buf= new StringBuilder(); + StringBuilder buf = new StringBuilder(); if (!pack.isDefaultPackage()) { buf.append("package ").append(pack.getElementName()).append(';'); //$NON-NLS-1$ } - buf.append(lineDelimiter).append(lineDelimiter); + buf.append(lineDelim).append(lineDelim); if (typeComment != null) { - buf.append(typeComment).append(lineDelimiter); + buf.append(typeComment).append(lineDelim); } buf.append(typeContent); return buf.toString(); } - /** - * Returns the created type or null is the type has not been created yet. The method + * Returns the created type or null if the type has not been created yet. The method * only returns a valid type after createType has been called. - * - * @return the created type + * @return the created type or null * @see #createType(IProgressMonitor) */ public IType getCreatedType() { - return fCreatedType; + return fCreatedTypes.stream() + .findFirst() + .orElse(null); } // ---- construct CU body---------------- - private void writeSuperClass(StringBuffer buf, ImportsManager imports) { - String superclass= getSuperClass(); - if (fTypeKind == CLASS_TYPE && superclass.length() > 0 && !"java.lang.Object".equals(superclass)) { //$NON-NLS-1$ + /** + * Writes the super class. + * @param currentType Current type + * @param typeName Type name + * @param buf Write buffer + * @param imports Imports manager + */ + private void writeSuperClass(IType currentType, String typeName, StringBuffer buf, ImportsManager imports) { + String superclass = getSuperClass(); + if (fTypeKind == CLASS_TYPE && !superclass.isEmpty() && !"java.lang.Object".equals(superclass)) { //$NON-NLS-1$ buf.append(" extends "); //$NON-NLS-1$ - ITypeBinding binding= null; - if (fCurrType != null) { - binding= TypeContextChecker.resolveSuperClass(superclass, fCurrType, getSuperClassStubTypeContext()); - } - if (binding != null) { - buf.append(imports.addImport(binding)); - } else { - buf.append(imports.addImport(superclass)); + ITypeBinding binding = null; + if (currentType != null) { + StubTypeContext superClassStubTypeContext = getSuperClassStubTypeContext(typeName); + binding = TypeContextChecker.resolveSuperClass(superclass, currentType, superClassStubTypeContext); } + buf.append(binding == null ? imports.addImport(superclass) : imports.addImport(binding)); } } - private void writeSuperInterfaces(StringBuffer buf, ImportsManager imports) { - List interfaces= getSuperInterfaces(); - int last= interfaces.size() - 1; + /** + * Writes the super interfaces. + * @param currentType Current type + * @param typeName Type name + * @param buf Write buffer + * @param imports Imports manager + */ + private void writeSuperInterfaces(IType currentType, String typeName, StringBuffer buf, ImportsManager imports) { + List interfaces = getSuperInterfaces(); + int last = interfaces.size() - 1; if (last >= 0) { - if (fTypeKind != INTERFACE_TYPE) { - buf.append(" implements "); //$NON-NLS-1$ - } else { - buf.append(" extends "); //$NON-NLS-1$ - } - String[] intfs= interfaces.toArray(new String[interfaces.size()]); + buf.append(fTypeKind == INTERFACE_TYPE ? " extends " : " implements "); //$NON-NLS-1$ //$NON-NLS-2$ + String[] intfs = interfaces.toArray(new String[interfaces.size()]); ITypeBinding[] bindings; - if (fCurrType != null) { - bindings= TypeContextChecker.resolveSuperInterfaces(intfs, fCurrType, getSuperInterfacesStubTypeContext()); + if (currentType != null) { + StubTypeContext superInterfacesStubTypeCtx = getSuperInterfacesStubTypeContext(typeName); + bindings = TypeContextChecker.resolveSuperInterfaces(intfs, currentType, superInterfacesStubTypeCtx); } else { - bindings= new ITypeBinding[intfs.length]; + bindings = new ITypeBinding[intfs.length]; } - for (int i= 0; i <= last; i++) { - ITypeBinding binding= bindings[i]; + for (int i = 0; i <= last; i++) { + ITypeBinding binding = bindings[i]; if (binding != null) { buf.append(imports.addImport(binding)); } else { @@ -3069,59 +3300,70 @@ private void writeSuperInterfaces(StringBuffer buf, ImportsManager imports) { } } - - private String constructSimpleTypeStub() { - StringBuilder buf= new StringBuilder("public class "); //$NON-NLS-1$ - buf.append(getTypeName()); - buf.append("{ }"); //$NON-NLS-1$ - return buf.toString(); + /** + * Constructs a simple type stub. + * @param typeName Type name + * @return A simple type stub + */ + private String constructSimpleTypeStub(String typeName) { + return String.format("public class %s{}", typeName); //$NON-NLS-1$ } - /* - * Called from createType to construct the source for this type + /** + * Called from createType to construct the source for this type. + * @param currentType Current type + * @param tnv Type name variants + * @param parentCU Parent compilation unit + * @param imports Imports manager + * @param lineDelimiter Line delimiter to use + * @return Type stub + * @throws CoreException Thrown when the creation failed */ - private String constructTypeStub(ICompilationUnit parentCU, ImportsManager imports, String lineDelimiter) throws CoreException { - StringBuffer buf= new StringBuffer(); + private String constructTypeStub(IType currentType, TypeNameVariants tnv, ICompilationUnit parentCU, + ImportsManager imports, String lineDelimiter) throws CoreException { - int modifiers= getModifiers(); + StringBuffer buf = new StringBuffer(); + int modifiers = getModifiers(); buf.append(Flags.toString(modifiers)); if (modifiers != 0) { buf.append(' '); } - String type= ""; //$NON-NLS-1$ - String templateID= ""; //$NON-NLS-1$ + String type = ""; //$NON-NLS-1$ + String templateID = ""; //$NON-NLS-1$ switch (fTypeKind) { case CLASS_TYPE: - type= "class "; //$NON-NLS-1$ - templateID= CodeGeneration.CLASS_BODY_TEMPLATE_ID; + type = "class "; //$NON-NLS-1$ + templateID = CodeGeneration.CLASS_BODY_TEMPLATE_ID; break; case INTERFACE_TYPE: - type= "interface "; //$NON-NLS-1$ - templateID= CodeGeneration.INTERFACE_BODY_TEMPLATE_ID; + type = "interface "; //$NON-NLS-1$ + templateID = CodeGeneration.INTERFACE_BODY_TEMPLATE_ID; break; case ENUM_TYPE: - type= "enum "; //$NON-NLS-1$ - templateID= CodeGeneration.ENUM_BODY_TEMPLATE_ID; + type = "enum "; //$NON-NLS-1$ + templateID = CodeGeneration.ENUM_BODY_TEMPLATE_ID; break; case ANNOTATION_TYPE: - type= "@interface "; //$NON-NLS-1$ - templateID= CodeGeneration.ANNOTATION_BODY_TEMPLATE_ID; + type = "@interface "; //$NON-NLS-1$ + templateID = CodeGeneration.ANNOTATION_BODY_TEMPLATE_ID; break; case RECORD_TYPE: - type= "record "; //$NON-NLS-1$ - templateID= CodeGeneration.RECORD_BODY_TEMPLATE_ID; + type = "record "; //$NON-NLS-1$ + templateID = CodeGeneration.RECORD_BODY_TEMPLATE_ID; break; + default: + // Do nothing } buf.append(type); - buf.append(getTypeName()); + buf.append(tnv.nameWithParams); if (fTypeKind == RECORD_TYPE) { buf.append("()"); //$NON-NLS-1$ } - writeSuperClass(buf, imports); - writeSuperInterfaces(buf, imports); + writeSuperClass(currentType, tnv.nameWithoutParams, buf, imports); + writeSuperInterfaces(currentType, tnv.nameWithoutParams, buf, imports); buf.append(" {").append(lineDelimiter); //$NON-NLS-1$ - String typeBody= CodeGeneration.getTypeBody(templateID, parentCU, getTypeName(), lineDelimiter); + String typeBody = CodeGeneration.getTypeBody(templateID, parentCU, tnv.nameWithoutParams, lineDelimiter); if (typeBody != null) { buf.append(typeBody); } else { @@ -3135,8 +3377,7 @@ private String constructTypeStub(ICompilationUnit parentCU, ImportsManager impor * Hook method that gets called from createType to support adding of * unanticipated methods, fields, and inner types to the created type. *

- * Implementers can use any methods defined on IType to manipulate the - * new type. + * Implementers can use any methods defined on IType to manipulate the new type. *

*

* The source code of the new type will be formatted using the platform's formatter. Needed @@ -3148,23 +3389,23 @@ private String constructTypeStub(ICompilationUnit parentCU, ImportsManager impor * @param imports an import manager which can be used to add new imports * @param monitor a progress monitor to report progress. Must not be null * @throws CoreException thrown when creation of the type members failed - * * @see #createType(IProgressMonitor) */ - protected void createTypeMembers(IType newType, final ImportsManager imports, IProgressMonitor monitor) throws CoreException { + protected void createTypeMembers(IType newType, ImportsManager imports, IProgressMonitor monitor) + throws CoreException { + // default implementation does nothing // example would be - // String mainMathod= "public void foo(Vector vec) {}" + // String mainMathod = "public void foo(Vector vec) {}" // createdType.createMethod(main, null, false, null); // imports.addImport("java.lang.Vector"); } - /** + * Gets the file template or null. * @param parentCU the current compilation unit * @return returns the file template or null - * @deprecated Instead of file templates, the new type code template - * specifies the stub for a compilation unit. + * @deprecated Instead of file templates, the new type code template specifies the stub for a compilation unit. */ @Deprecated protected String getFileComment(ICompilationUnit parentCU) { @@ -3172,85 +3413,69 @@ protected String getFileComment(ICompilationUnit parentCU) { } /** - * Hook method that gets called from createType to retrieve - * a file comment. This default implementation returns the content of the - * 'file comment' template or null if no comment should be created. - * + * Hook method that gets called from createType to retrieve a file comment. This default + * implementation returns the content of the 'file comment' template or null if no comment should + * be created. * @param parentCU the parent compilation unit * @param lineDelimiter the line delimiter to use - * @return the file comment or null if a file comment - * is not desired + * @return the file comment or null if a file comment is not desired * @throws CoreException when fetching the file comment fails - * - * @since 3.1 + * @since 3.1 */ protected String getFileComment(ICompilationUnit parentCU, String lineDelimiter) throws CoreException { - if (isAddComments()) { - return CodeGeneration.getFileComment(parentCU, lineDelimiter); - } - return null; - + return isAddComments() ? CodeGeneration.getFileComment(parentCU, lineDelimiter) : null; } + /** + * Checks if the input is a valid comment. + * @param template Input to check + * @return True if the input is a valid comment + */ private boolean isValidComment(String template) { - IScanner scanner= ToolFactory.createScanner(true, false, false, false); + IScanner scanner = ToolFactory.createScanner(true, false, false, false); scanner.setSource(template.toCharArray()); try { - int next= scanner.getNextToken(); + int next = scanner.getNextToken(); while (TokenScanner.isComment(next)) { - next= scanner.getNextToken(); + next = scanner.getNextToken(); } return next == ITerminalSymbols.TokenNameEOF; } catch (InvalidInputException e) { + return false; } - return false; } /** - * Hook method that gets called from createType to retrieve - * a type comment. This default implementation returns the content of the - * 'type comment' template. - * + * Hook method that gets called from createType to retrieve a type comment. This default + * implementation returns the content of the 'type comment' template. + * @param typeName Type name * @param parentCU the parent compilation unit - * @param lineDelimiter the line delimiter to use - * @return the type comment or null if a type comment - * is not desired - * - * @since 3.0 + * @param lineDelim the line delimiter to use + * @return the type comment or null if a type comment is not desired + * @since 3.33 */ - protected String getTypeComment(ICompilationUnit parentCU, String lineDelimiter) { - if (isAddComments()) { - try { - StringBuilder typeName= new StringBuilder(); - if (isEnclosingTypeSelected()) { - typeName.append(getEnclosingType().getTypeQualifiedName('.')).append('.'); - } - typeName.append(getTypeNameWithoutParameters()); - String[] typeParamNames= new String[0]; - String comment= CodeGeneration.getTypeComment(parentCU, typeName.toString(), typeParamNames, lineDelimiter); - if (comment != null && isValidComment(comment)) { - return comment; - } - } catch (CoreException e) { - JavaPlugin.log(e); + protected String getTypeComment(String typeName, ICompilationUnit parentCU, String lineDelim) { + if (!isAddComments()) { + return null; + } + try { + StringBuilder typeNameSB = new StringBuilder(); + if (isEnclosingTypeSelected()) { + typeNameSB.append(getEnclosingType().getTypeQualifiedName('.')).append('.'); } + typeNameSB.append(typeName); + String comment = CodeGeneration.getTypeComment(parentCU, typeNameSB.toString(), new String[0], lineDelim); + if (comment != null && isValidComment(comment)) { + return comment; + } + } catch (CoreException e) { + JavaPlugin.log(e); } return null; } /** - * @param parentCU the current compilation unit - * @return returns the template or null - * @deprecated Use getTypeComment(ICompilationUnit, String) - */ - @Deprecated - protected String getTypeComment(ICompilationUnit parentCU) { - if (StubUtility.doAddComments(parentCU.getJavaProject())) - return getTypeComment(parentCU, StubUtility.getLineDelimiterUsed(parentCU)); - return null; - } - - /** + * Answers the template. * @param name the name of the template * @param parentCU the current compilation unit * @return returns the template or null @@ -3261,23 +3486,19 @@ protected String getTemplate(String name, ICompilationUnit parentCU) { return getTemplate(name, parentCU, 0); } - /** - * Returns the string resulting from evaluation the given template in - * the context of the given compilation unit. This accesses the normal - * template page, not the code templates. To use code templates use - * constructCUContent to construct a compilation unit stub or - * getTypeComment for the comment of the type. + * Returns the string resulting from evaluation the given template in the context of the given compilation unit. + * This accesses the normal template page, not the code templates. To use code templates use + * constructCUContent to construct a compilation unit stub or getTypeComment for the type comment. * * @param name the template to be evaluated * @param parentCU the templates evaluation context - * @param pos a source offset into the parent compilation unit. The - * template is evaluated at the given source offset + * @param pos Source offset into the parent compilation unit. The template is evaluated at the given source offset. * @return return the template with the given name or null if the template could not be found. */ protected String getTemplate(String name, ICompilationUnit parentCU, int pos) { try { - Template template= JavaPlugin.getDefault().getTemplateStore().findTemplate(name); + Template template = JavaPlugin.getDefault().getTemplateStore().findTemplate(name); if (template != null) { return TemplateUtils.evaluateTemplate(template, parentCU, pos); } @@ -3288,37 +3509,39 @@ protected String getTemplate(String name, ICompilationUnit parentCU, int pos) { } /** - * Creates the stub for 'public static void main(String[] args)' method - * + * Creates the stub for 'public static void main(String[] args)' method. * @param type the type for which the main method is to be created * @param imports an import manager to add all needed import statements * @return the created method. * @throws CoreException thrown when the creation fails. * @since 3.25 */ - protected IMethod createMainMethod(IType type, ImportsManager imports) throws CoreException{ - if (type != null ) { - StringBuilder buf= new StringBuilder(); - final String lineDelim= "\n"; // OK, since content is formatted afterwards //$NON-NLS-1$ - if (isAddComments()) { - String comment= CodeGeneration.getMethodComment(type.getCompilationUnit(), type.getTypeQualifiedName('.'), "main", new String[] { "args" }, new String[0], Signature.createTypeSignature("void", true), null, lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - if (comment != null) { - buf.append(comment); - buf.append(lineDelim); - } + protected IMethod createMainMethod(IType type, ImportsManager imports) throws CoreException { + if (type == null) { + return null; + } + StringBuilder buf = new StringBuilder(); + final String lineDelim = "\n"; // OK, since content is formatted afterwards //$NON-NLS-1$ + ICompilationUnit cu = type.getCompilationUnit(); + String qName = type.getTypeQualifiedName('.'); + if (isAddComments()) { + String comment = CodeGeneration.getMethodComment(cu, qName, "main", new String[] { "args" }, new String[0], Signature.createTypeSignature("void", true), null, lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + if (comment != null) { + buf.append(comment); + buf.append(lineDelim); } - buf.append("public static void main("); //$NON-NLS-1$ - buf.append(imports.addImport("java.lang.String")); //$NON-NLS-1$ - buf.append("[] args) {"); //$NON-NLS-1$ - buf.append(lineDelim); - final String content= CodeGeneration.getMethodBodyContent(type.getCompilationUnit(), type.getTypeQualifiedName('.'), "main", false, "", lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ - if (content != null && content.length() != 0) - buf.append(content); - buf.append(lineDelim); - buf.append("}"); //$NON-NLS-1$ - return type.createMethod(buf.toString(), null, false, null); } - return null; + buf.append("public static void main("); //$NON-NLS-1$ + buf.append(imports.addImport("java.lang.String")); //$NON-NLS-1$ + buf.append("[] args) {"); //$NON-NLS-1$ + buf.append(lineDelim); + String content = CodeGeneration.getMethodBodyContent(cu, qName, "main", false, "", lineDelim); //$NON-NLS-1$ //$NON-NLS-2$ + if (content != null && !content.isEmpty()) { + buf.append(content); + } + buf.append(lineDelim); + buf.append("}"); //$NON-NLS-1$ + return type.createMethod(buf.toString(), null, false, null); } /** @@ -3334,32 +3557,34 @@ protected IMethod createMainMethod(IType type, ImportsManager imports) throws Co * @return the created methods. * @throws CoreException thrown when the creation fails. */ - protected IMethod[] createInheritedMethods(IType type, boolean doConstructors, boolean doUnimplementedMethods, ImportsManager imports, IProgressMonitor monitor) throws CoreException { - SubMonitor subMonitor= SubMonitor.convert(monitor, 3); - final ICompilationUnit cu= type.getCompilationUnit(); + protected IMethod[] createInheritedMethods(IType type, boolean doConstructors, boolean doUnimplementedMethods, + ImportsManager imports, IProgressMonitor monitor) throws CoreException { + + SubMonitor subMonitor = SubMonitor.convert(monitor, 3); + final ICompilationUnit cu = type.getCompilationUnit(); JavaModelUtil.reconcile(cu); - IMethod[] typeMethods= type.getMethods(); - Set handleIds= new HashSet<>(typeMethods.length); + IMethod[] typeMethods = type.getMethods(); + Set handleIds = new HashSet<>(typeMethods.length); for (IMethod typeMethod : typeMethods) { handleIds.add(typeMethod.getHandleIdentifier()); } - ArrayList newMethods= new ArrayList<>(); - CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings(type.getJavaProject()); - settings.createComments= isAddComments(); - ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); + CodeGenerationSettings settings = JavaPreferencesSettings.getCodeGenerationSettings(type.getJavaProject()); + settings.createComments = isAddComments(); + ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); parser.setResolveBindings(true); parser.setSource(cu); - CompilationUnit unit= (CompilationUnit) parser.createAST(subMonitor.newChild(1)); - final ITypeBinding binding= ASTNodes.getTypeBinding(unit, type); + CompilationUnit unit = (CompilationUnit) parser.createAST(subMonitor.newChild(1)); + final ITypeBinding binding = ASTNodes.getTypeBinding(unit, type); if (binding != null) { if (doUnimplementedMethods) { - AddUnimplementedMethodsOperation operation= new AddUnimplementedMethodsOperation(unit, binding, null, -1, false, true, false); + var operation = new AddUnimplementedMethodsOperation(unit, binding, null, -1, false, true, false); operation.setCreateComments(isAddComments()); operation.run(subMonitor.newChild(1)); createImports(imports, operation.getCreatedImports()); } if (doConstructors) { - AddUnimplementedConstructorsOperation operation= new AddUnimplementedConstructorsOperation(unit, binding, null, -1, false, true, false, FormatterProfileManager.getProjectSettings(type.getJavaProject())); + var operation = new AddUnimplementedConstructorsOperation(unit, binding, null, -1, false, true, false, + FormatterProfileManager.getProjectSettings(type.getJavaProject())); operation.setOmitSuper(true); operation.setCreateComments(isAddComments()); operation.run(subMonitor.newChild(1)); @@ -3367,110 +3592,132 @@ protected IMethod[] createInheritedMethods(IType type, boolean doConstructors, b } } JavaModelUtil.reconcile(cu); + ArrayList newMethods = new ArrayList<>(); for (IMethod typeMethod : type.getMethods()) { if (!handleIds.contains(typeMethod.getHandleIdentifier())) { newMethods.add(typeMethod); } } - IMethod[] methods= new IMethod[newMethods.size()]; + IMethod[] methods = new IMethod[newMethods.size()]; newMethods.toArray(methods); return methods; } + /** + * Creates/adds imports. + * @param imports Imports manager + * @param createdImports Imports to add + */ private void createImports(ImportsManager imports, String[] createdImports) { - for (String createdImport : createdImports) { - imports.addImport(createdImport); - } + Arrays.stream(createdImports).forEach(imports::addImport); } - private ITypeBinding getCreatedTypeBinding(boolean reset) { - if (fCreatedTypeBinding != null && !reset) - return fCreatedTypeBinding; - if (fCreatedType != null) { - final ICompilationUnit cu= fCreatedType.getCompilationUnit(); - ASTParser parser2= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); - parser2.setResolveBindings(true); - parser2.setSource(cu); - CompilationUnit unit= (CompilationUnit) parser2.createAST(new NullProgressMonitor()); - try { - TypeDeclaration typeDecl= ASTNodeSearchUtil.getTypeDeclarationNode(fCreatedType, unit); - if (typeDecl != null) { - return typeDecl.resolveBinding(); - } - } catch (JavaModelException e) { - // do nothing - } + /** + * Creates a type binding for the given type. + * @param type The type + * @return Created type binding + */ + private ITypeBinding createTypeBinding(IType type) { + if (type == null) { + return null; + } + ASTParser parser2 = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); + parser2.setResolveBindings(true); + parser2.setSource(type.getCompilationUnit()); + CompilationUnit unit = (CompilationUnit) parser2.createAST(new NullProgressMonitor()); + try { + TypeDeclaration typeDecl = ASTNodeSearchUtil.getTypeDeclarationNode(type, unit); + return typeDecl == null ? null : typeDecl.resolveBinding(); + } catch (JavaModelException e) { + return null; } - return null; } - private void updateSealedSuperClass() { - updateSealedSuperType(fSuperClass); + /** + * Updates sealed superclass. + * @param createdType Created type + * @param typeName Type name + */ + private void updateSealedSuperClass(IType createdType, String typeName) { + updateSealedSuperType(createdType, typeName, fSuperClass); } - private void updateSealedSuperInterfaces() { - List elements= fSuperInterfacesDialogField.getElements(); - for (InterfaceWrapper element : elements) { - updateSealedSuperType(element.getType()); - } + /** + * Updates sealed super interfaces. + * @param createdType Created type + * @param typeName Type name + */ + private void updateSealedSuperInterfaces(IType createdType, String typeName) { + fSuperInterfacesDialogField.getElements().forEach( + iw -> updateSealedSuperType(createdType, typeName, iw.getType())); } - private void updateSealedSuperTypes() { - if (fCreatedType != null && isSuperTypeSealed()) { - getCreatedTypeBinding(true); - updateSealedSuperClass(); - updateSealedSuperInterfaces(); + /** + * Updates sealed super types. + * @param createdType Created type + * @param typeName Type name + */ + private void updateSealedSuperTypes(IType createdType, String typeName) { + if (createdType != null && isSuperTypeSealed()) { + updateSealedSuperClass(createdType, typeName); + updateSealedSuperInterfaces(createdType, typeName); } } + /** + * Checks if the super type is also the enclosing type. + * @param superType Super type + * @return True if the super type is also the enclosing type + */ private boolean isSuperTypeEnclosingType(IType superType) { - boolean val= false; - if (isEnclosingTypeSelected() && superType != null && superType.equals(fCurrEnclosingType)) { - val= true; - } - return val; + return isEnclosingTypeSelected() && superType != null && superType.equals(fCurrEnclosingType); } - private void updateSealedSuperType(IType superType) { + /** + * Updates sealed super type. + * @param createdType Created type + * @param typeName Type name + * @param superType Super type + */ + private void updateSealedSuperType(IType createdType, String typeName, IType superType) { try { if (superType != null - && superType.isSealed() && fCreatedType != null && !isSuperTypeEnclosingType(superType)) { - String typeName= getTypeNameWithoutParameters(); - String[] names= superType.getPermittedSubtypeNames(); - List nameList= Arrays.asList(names); + && superType.isSealed() && createdType != null && !isSuperTypeEnclosingType(superType)) { + String[] names = superType.getPermittedSubtypeNames(); + List nameList = Arrays.asList(names); if (!nameList.contains(typeName)) { - final ICompilationUnit cu= superType.getCompilationUnit(); - IPackageFragment parent= superType.getPackageFragment(); - IPackageFragment child= fCreatedType.getPackageFragment(); - boolean importTobeAdded= false; + final ICompilationUnit cu = superType.getCompilationUnit(); + IPackageFragment parent = superType.getPackageFragment(); + IPackageFragment child = createdType.getPackageFragment(); + boolean importTobeAdded = false; if (parent != null && !parent.equals(child)) { - importTobeAdded= true; + importTobeAdded = true; } JavaModelUtil.reconcile(cu); - ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); + ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); parser.setResolveBindings(true); parser.setSource(cu); - CompilationUnitRewrite cuRewrite= new CompilationUnitRewrite(cu); - TypeDeclaration typeDecl= ASTNodeSearchUtil.getTypeDeclarationNode(superType, cuRewrite.getRoot()); + CompilationUnitRewrite cuRewrite = new CompilationUnitRewrite(cu); + TypeDeclaration typeDecl = ASTNodeSearchUtil.getTypeDeclarationNode(superType, cuRewrite.getRoot()); if (typeDecl != null) { - ASTRewrite astRewrite= cuRewrite.getASTRewrite(); - AST ast= astRewrite.getAST(); - Type astType= ast.newSimpleType(ast.newSimpleName(typeName)); + ASTRewrite astRewrite = cuRewrite.getASTRewrite(); + AST ast = astRewrite.getAST(); + Type astType = ast.newSimpleType(ast.newSimpleName(typeName)); astRewrite.getListRewrite(typeDecl, TypeDeclaration.PERMITS_TYPES_PROPERTY).insertLast(astType, null); - TextEdit tEdit= astRewrite.rewriteAST(); - ImportRewrite importRewrite= null; + TextEdit tEdit = astRewrite.rewriteAST(); + ImportRewrite importRewrite = null; if (importTobeAdded) { - ITypeBinding typeBinding= this.getCreatedTypeBinding(false); + ITypeBinding typeBinding = createTypeBinding(createdType); if (typeBinding != null) { - importRewrite= StubUtility.createImportRewrite(cu, true); - ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(typeDecl.getRoot(), importRewrite); - importRewrite.addImport(typeBinding, importRewriteContext); + importRewrite = StubUtility.createImportRewrite(cu, true); + var ctx = new ContextSensitiveImportRewriteContext(typeDecl.getRoot(), importRewrite); + importRewrite.addImport(typeBinding, ctx); } } try { JavaModelUtil.applyEdit(cu, tEdit, true, new NullProgressMonitor()); if (importRewrite != null) { - TextEdit iEdit= importRewrite.rewriteImports(new NullProgressMonitor()); + TextEdit iEdit = importRewrite.rewriteImports(new NullProgressMonitor()); JavaModelUtil.applyEdit(cu, iEdit, true, new NullProgressMonitor()); } cu.commitWorkingCopy(true, new NullProgressMonitor()); @@ -3481,24 +3728,22 @@ private void updateSealedSuperType(IType superType) { } } } catch (JavaModelException e) { - //do nothing + // do nothing } } - // ---- creation ---------------- /** * Returns the runnable that creates the type using the current settings. * The returned runnable must be executed in the UI thread. - * * @return the runnable to create the new type */ public IRunnableWithProgress getRunnable() { return monitor -> { try { if (monitor == null) { - monitor= new NullProgressMonitor(); + monitor = new NullProgressMonitor(); } createType(monitor); } catch (CoreException e) { @@ -3507,12 +3752,17 @@ public IRunnableWithProgress getRunnable() { }; } + /** + * Sets the non sealed supported flag. + * @param project Java project + */ private void setIsNonSealedSupported(IJavaProject project) { - fIsSealedSupported= (project != null && JavaModelUtil.is17OrHigher(project)); + fIsSealedSupported = project != null && JavaModelUtil.is17OrHigher(project); initOtherButtons(); } /** + * Getter. * @return the error status based on super class * @since 3.25 */ @@ -3521,6 +3771,16 @@ public IStatus getSuperClassStatus() { } /** + * Getter. + * @return the error status based on type name(s) + * @since 3.33 + */ + public IStatus getTypeNameStatus() { + return this.fTypeNameStatus; + } + + /** + * Getter. * @return the error status based on super interface * @since 3.25 */ @@ -3529,6 +3789,7 @@ public IStatus getSuperInterfaceStatus() { } /** + * Getter. * @return the error status based on super class * @since 3.25 */ @@ -3537,6 +3798,7 @@ public IStatus getSealedSuperClassStatus() { } /** + * Getter. * @return the error status based on super interface * @since 3.25 */ @@ -3545,10 +3807,11 @@ public IStatus getSealedSuperInterfaceStatus() { } /** + * Getter. * @return the error status based on super type * @since 3.25 */ public IStatus getSealedModifierStatus() { return this.fSealedModifierStatus; } -} +} \ No newline at end of file