IJ-CR-144148 [java] IDEA-358751 Java Annotations copied to generated getter / setter

- rework settings

GitOrigin-RevId: fc914bfed1b8046eccf2e76054c39f4c2ad7359c
This commit is contained in:
Mikhail Pyltsin
2024-09-12 19:41:09 +02:00
committed by intellij-monorepo-bot
parent 379719b7ea
commit 1f476ec640
14 changed files with 93 additions and 53 deletions

View File

@@ -19,14 +19,11 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
public interface EncapsulatableClassMember extends ClassMember {
/**
* @return PsiElement or TemplateGenerationInfo
* @deprecated please, use {@link EncapsulatableClassMember#generateGetter(EnumSet)}
* @deprecated please, use {@link EncapsulatableClassMember#generateGetter(SetterGetterGenerationOptions)}
*/
@Deprecated
@Nullable
@@ -34,7 +31,7 @@ public interface EncapsulatableClassMember extends ClassMember {
/**
* @return PsiElement or TemplateGenerationInfo
* @deprecated please, use {@link EncapsulatableClassMember#generateSetter(EnumSet)}
* @deprecated please, use {@link EncapsulatableClassMember#generateSetter(SetterGetterGenerationOptions)}
*/
@Deprecated
@Nullable
@@ -44,7 +41,7 @@ public interface EncapsulatableClassMember extends ClassMember {
* @return PsiElement or TemplateGenerationInfo
*/
@Nullable
default GenerationInfo generateGetter(@NotNull EnumSet<Option> options) throws IncorrectOperationException {
default GenerationInfo generateGetter(@NotNull SetterGetterGenerationOptions options) throws IncorrectOperationException {
return generateGetter();
}
@@ -52,7 +49,7 @@ public interface EncapsulatableClassMember extends ClassMember {
* @return PsiElement or TemplateGenerationInfo
*/
@Nullable
default GenerationInfo generateSetter(@NotNull EnumSet<Option> options) throws IncorrectOperationException {
default GenerationInfo generateSetter(@NotNull SetterGetterGenerationOptions options) throws IncorrectOperationException {
return generateSetter();
}
@@ -63,7 +60,4 @@ public interface EncapsulatableClassMember extends ClassMember {
return false;
}
enum Option {
COPY_ALL_ANNOTATIONS
}
}

View File

@@ -40,6 +40,7 @@ public class GenerateGetterAndSetterHandler extends GenerateGetterSetterHandlerB
@Override
public GenerationInfo[] generateMemberPrototypes(PsiClass aClass, ClassMember original) throws IncorrectOperationException {
if (aClass == null) return GenerationInfo.EMPTY_ARRAY;
myGenerateGetterHandler.myGenerateAnnotations = myGenerateAnnotations;
myGenerateSetterHandler.myGenerateAnnotations = myGenerateAnnotations;
ArrayList<GenerationInfo> array = new ArrayList<>();

View File

@@ -34,12 +34,14 @@ public class GenerateGetterHandler extends GenerateGetterSetterHandlerBase {
@Override
protected GenerationInfo[] generateMemberPrototypes(PsiClass aClass, ClassMember original) throws IncorrectOperationException {
if (aClass == null) return GenerationInfo.EMPTY_ARRAY;
if (original instanceof PropertyClassMember propertyClassMember) {
final GenerationInfo[] getters = propertyClassMember.generateGetters(aClass, getOptions());
if (getters != null) {
return getters;
}
} else if (original instanceof EncapsulatableClassMember encapsulatableClassMember) {
}
else if (original instanceof EncapsulatableClassMember encapsulatableClassMember) {
final GenerationInfo getter = encapsulatableClassMember.generateGetter(getOptions());
if (getter != null) {
return new GenerationInfo[]{getter};

View File

@@ -3,6 +3,7 @@ package com.intellij.codeInsight.generation;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.java.JavaBundle;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.options.ShowSettingsUtil;
@@ -31,7 +32,6 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
public abstract class GenerateGetterSetterHandlerBase extends GenerateMembersHandlerBase {
@@ -40,7 +40,7 @@ public abstract class GenerateGetterSetterHandlerBase extends GenerateMembersHan
protected boolean myGenerateAnnotations;
@Nullable
private JBCheckBox myGenerateAnnotationsCheckBox;
private boolean supportsAnnotations;
public GenerateGetterSetterHandlerBase(@NlsContexts.DialogTitle String chooserTitle) {
super(chooserTitle);
}
@@ -57,6 +57,9 @@ public abstract class GenerateGetterSetterHandlerBase extends GenerateMembersHan
@Override
protected ClassMember[] chooseOriginalMembers(PsiClass aClass, Project project, Editor editor) {
if (aClass.getLanguage() == JavaLanguage.INSTANCE) {
supportsAnnotations = true;
}
final ClassMember[] allMembers = getAllOriginalMembers(aClass);
if (allMembers == null) {
HintManager.getInstance().showErrorHint(editor, getNothingFoundMessage());
@@ -77,23 +80,27 @@ public abstract class GenerateGetterSetterHandlerBase extends GenerateMembersHan
@Nullable Editor editor) {
ClassMember[] chosenMembers = super.chooseMembers(members, allowEmptySelection, copyJavadocCheckbox, project, editor);
myGenerateAnnotations = myGenerateAnnotationsCheckBox != null && myGenerateAnnotationsCheckBox.isSelected();
project.getService(JavaGeneratorSettingsStorage.class).getState().setGenerateAllAnnotations(myGenerateAnnotations);
myGenerateAnnotationsCheckBox = null;
return chosenMembers;
}
@Override
protected JComponent @Nullable [] getOptionControls() {
protected JComponent @Nullable [] getOptionControls(@Nullable Project project) {
if (project == null) return null;
if (!supportsAnnotations) return null;
if (myGenerateAnnotationsCheckBox == null) {
myGenerateAnnotationsCheckBox = new JBCheckBox(JavaBundle.message("generate.getter.setter.generate.all.annotations"), false);
boolean annotations = project.getService(JavaGeneratorSettingsStorage.class).getState().getGenerateAllAnnotations();
myGenerateAnnotationsCheckBox = new JBCheckBox(JavaBundle.message("generate.getter.setter.generate.all.annotations"), annotations);
myGenerateAnnotationsCheckBox.setToolTipText(JavaBundle.message("generate.getter.setter.generate.all.annotations.tooltip"));
}
return new JComponent[] {myGenerateAnnotationsCheckBox};
return new JComponent[]{myGenerateAnnotationsCheckBox};
}
protected @NotNull EnumSet<EncapsulatableClassMember.Option> getOptions() {
protected @NotNull SetterGetterGenerationOptions getOptions() {
return myGenerateAnnotations
? EnumSet.of(EncapsulatableClassMember.Option.COPY_ALL_ANNOTATIONS)
: EnumSet.noneOf(EncapsulatableClassMember.Option.class);
? new SetterGetterGenerationOptions(true)
: new SetterGetterGenerationOptions(false);
}
protected static JComponent getHeaderPanel(final Project project, final TemplatesManager templatesManager, final @Nls String templatesTitle) {

View File

@@ -232,7 +232,7 @@ public abstract class GenerateMembersHandlerBase implements CodeInsightActionHan
boolean copyJavadocCheckbox,
Project project) {
MemberChooser<ClassMember> chooser =
new MemberChooser<>(members, allowEmptySelection, true, project, getHeaderPanel(project), getOptionControls()) {
new MemberChooser<>(members, allowEmptySelection, true, project, getHeaderPanel(project), getOptionControls(project)) {
@Override
protected @Nullable String getHelpId() {
return GenerateMembersHandlerBase.this.getHelpId();
@@ -247,6 +247,10 @@ public abstract class GenerateMembersHandlerBase implements CodeInsightActionHan
return null;
}
protected JComponent @Nullable [] getOptionControls(@Nullable Project project) {
return getOptionControls();
}
protected JComponent @Nullable [] getOptionControls() {
return null;
}

View File

@@ -763,29 +763,29 @@ public final class GenerateMembersUtil {
}
public static @NotNull PsiMethod generateSetterPrototype(@NotNull PsiField field, PsiClass aClass) {
return generatePrototype(field, aClass, true, EnumSet.noneOf(EncapsulatableClassMember.Option.class), SetterTemplatesManager.getInstance());
return generatePrototype(field, aClass, true, SetterGetterGenerationOptions.empty(), SetterTemplatesManager.getInstance());
}
static @NotNull PsiMethod generateGetterPrototype(@NotNull PsiField field, boolean ignoreInvalidTemplate) {
return generateGetterPrototype(field, ignoreInvalidTemplate, EnumSet.noneOf(EncapsulatableClassMember.Option.class));
return generateGetterPrototype(field, ignoreInvalidTemplate, SetterGetterGenerationOptions.empty());
}
static @NotNull PsiMethod generateSetterPrototype(@NotNull PsiField field, boolean ignoreInvalidTemplate) {
return generateSetterPrototype(field, ignoreInvalidTemplate, EnumSet.noneOf(EncapsulatableClassMember.Option.class));
return generateSetterPrototype(field, ignoreInvalidTemplate, SetterGetterGenerationOptions.empty());
}
static @NotNull PsiMethod generateGetterPrototype(@NotNull PsiField field, boolean ignoreInvalidTemplate, @NotNull EnumSet<EncapsulatableClassMember.Option> options) {
static @NotNull PsiMethod generateGetterPrototype(@NotNull PsiField field, boolean ignoreInvalidTemplate, @NotNull SetterGetterGenerationOptions options) {
return generatePrototype(field, field.getContainingClass(), ignoreInvalidTemplate, options, GetterTemplatesManager.getInstance());
}
static @NotNull PsiMethod generateSetterPrototype(@NotNull PsiField field, boolean ignoreInvalidTemplate, @NotNull EnumSet<EncapsulatableClassMember.Option> options) {
static @NotNull PsiMethod generateSetterPrototype(@NotNull PsiField field, boolean ignoreInvalidTemplate, @NotNull SetterGetterGenerationOptions options) {
return generatePrototype(field, field.getContainingClass(), ignoreInvalidTemplate, options, SetterTemplatesManager.getInstance());
}
private static @NotNull PsiMethod generatePrototype(@NotNull PsiField field,
PsiClass psiClass,
boolean ignoreInvalidTemplate,
@NotNull EnumSet<EncapsulatableClassMember.Option> options,
@NotNull SetterGetterGenerationOptions options,
@NotNull TemplatesManager templatesManager) {
Project project = field.getProject();
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
@@ -833,8 +833,7 @@ public final class GenerateMembersUtil {
}
if (annotationTarget != null) {
PsiType fieldType = field.getType();
String type = options.contains(EncapsulatableClassMember.Option.COPY_ALL_ANNOTATIONS) ? fieldType.getCanonicalText(true) :
getTypeWithNullableAnnotations(factory, fieldType);
String type = options.copyAllAnnotations() ? fieldType.getCanonicalText(true) : getTypeWithNullableAnnotations(factory, fieldType);
if (annotationTarget instanceof PsiParameter psiParameter && psiParameter.getTypeElement() != null) {
psiParameter.getTypeElement().replace(factory.createTypeElementFromText(type, psiParameter));
}

View File

@@ -36,6 +36,7 @@ public class GenerateSetterHandler extends GenerateGetterSetterHandlerBase {
@Override
protected GenerationInfo[] generateMemberPrototypes(PsiClass aClass, ClassMember original) throws IncorrectOperationException {
if (aClass == null) return GenerationInfo.EMPTY_ARRAY;
if (original instanceof PropertyClassMember propertyClassMember) {
final GenerationInfo[] getters = propertyClassMember.generateSetters(aClass, getOptions());
if (getters != null) {

View File

@@ -11,8 +11,6 @@ import com.intellij.util.indexing.DumbModeAccessType;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.EnumSet;
public abstract class GetterSetterPrototypeProvider {
public static final ExtensionPointName<GetterSetterPrototypeProvider> EP_NAME = ExtensionPointName.create("com.intellij.getterSetterProvider");
@Contract(pure = true)
@@ -44,13 +42,13 @@ public abstract class GetterSetterPrototypeProvider {
public static PsiMethod[] generateGetterSetters(PsiField field,
boolean generateGetter,
boolean ignoreInvalidTemplate) {
return generateGetterSetters(field, generateGetter, ignoreInvalidTemplate, EnumSet.noneOf(EncapsulatableClassMember.Option.class));
return generateGetterSetters(field, generateGetter, ignoreInvalidTemplate, SetterGetterGenerationOptions.empty());
}
public static PsiMethod[] generateGetterSetters(PsiField field,
boolean generateGetter,
boolean ignoreInvalidTemplate,
@NotNull EnumSet<EncapsulatableClassMember.Option> options) {
@NotNull SetterGetterGenerationOptions options) {
for (GetterSetterPrototypeProvider provider : EP_NAME.getExtensionList()) {
if (provider.canGeneratePrototypeFor(field)) {
return generateGetter ? provider.generateGetters(field) : provider.generateSetters(field);

View File

@@ -0,0 +1,14 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.generation
import com.intellij.openapi.components.*
@Service(Service.Level.PROJECT)
@State(name = "JavaGeneratorSettingsStorage",
storages = [Storage(StoragePathMacros.WORKSPACE_FILE)])
class JavaGeneratorSettingsStorage : SimplePersistentStateComponent<JavaGeneratorSettingsStorage.State>(State()) {
class State : BaseState() {
var generateAllAnnotations: Boolean by property(false)
}
}

View File

@@ -20,19 +20,17 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
public interface PropertyClassMember extends EncapsulatableClassMember {
/**
* @return PsiElement or TemplateGenerationInfo
* @deprecated please, use {@link PropertyClassMember#generateGetters(PsiClass, EnumSet)}
* @deprecated please, use {@link PropertyClassMember#generateGetters(PsiClass, SetterGetterGenerationOptions)}
*/
@Deprecated
GenerationInfo @Nullable [] generateGetters(PsiClass aClass) throws IncorrectOperationException;
/**
* @return PsiElement or TemplateGenerationInfo
* @deprecated please, use {@link PropertyClassMember#generateSetters(PsiClass, EnumSet)}
* @deprecated please, use {@link PropertyClassMember#generateSetters(PsiClass, SetterGetterGenerationOptions)}
*/
@Deprecated
GenerationInfo @Nullable [] generateSetters(PsiClass aClass) throws IncorrectOperationException;
@@ -40,14 +38,14 @@ public interface PropertyClassMember extends EncapsulatableClassMember {
/**
* @return PsiElement or TemplateGenerationInfo
*/
default GenerationInfo @Nullable [] generateGetters(PsiClass aClass, @NotNull EnumSet<Option> options) throws IncorrectOperationException{
default GenerationInfo @Nullable [] generateGetters(@NotNull PsiClass aClass, @NotNull SetterGetterGenerationOptions options) throws IncorrectOperationException{
return generateGetters(aClass);
}
/**
* @return PsiElement or TemplateGenerationInfo
*/
default GenerationInfo @Nullable [] generateSetters(PsiClass aClass, @NotNull EnumSet<Option> options) throws IncorrectOperationException{
default GenerationInfo @Nullable [] generateSetters(@NotNull PsiClass aClass, @NotNull SetterGetterGenerationOptions options) throws IncorrectOperationException{
return generateSetters(aClass);
}
}

View File

@@ -9,7 +9,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
public class PsiFieldMember extends PsiElementClassMember<PsiField> implements PropertyClassMember {
@@ -25,17 +24,25 @@ public class PsiFieldMember extends PsiElementClassMember<PsiField> implements P
@Override
public @Nullable GenerationInfo generateGetter() throws IncorrectOperationException {
final GenerationInfo[] infos = generateGetters(getElement().getContainingClass());
return generateGetter(SetterGetterGenerationOptions.empty());
}
@Override
public @Nullable GenerationInfo generateGetter(@NotNull SetterGetterGenerationOptions options) throws IncorrectOperationException {
PsiClass containingClass = getElement().getContainingClass();
if(containingClass == null) return null;
final GenerationInfo[] infos = generateGetters(containingClass, options);
return infos != null && infos.length > 0 ? infos[0] : null;
}
@Override
public GenerationInfo @Nullable [] generateGetters(PsiClass aClass) throws IncorrectOperationException {
return generateGetters(aClass, EnumSet.noneOf(Option.class));
if (aClass == null) return null;
return generateGetters(aClass, SetterGetterGenerationOptions.empty());
}
@Override
public GenerationInfo @Nullable [] generateGetters(PsiClass aClass, @NotNull EnumSet<Option> options) throws IncorrectOperationException {
public GenerationInfo @Nullable [] generateGetters(@NotNull PsiClass aClass, @NotNull SetterGetterGenerationOptions options) throws IncorrectOperationException {
PsiField field = getElement();
if (field.hasModifierProperty(PsiModifier.STATIC) &&
field.hasModifierProperty(PsiModifier.FINAL)) {
@@ -47,7 +54,14 @@ public class PsiFieldMember extends PsiElementClassMember<PsiField> implements P
@Override
public @Nullable GenerationInfo generateSetter() throws IncorrectOperationException {
final GenerationInfo[] infos = generateSetters(getElement().getContainingClass());
return generateSetter(SetterGetterGenerationOptions.empty());
}
@Override
public @Nullable GenerationInfo generateSetter(@NotNull SetterGetterGenerationOptions options) throws IncorrectOperationException {
PsiClass containingClass = getElement().getContainingClass();
if (containingClass == null) return null;
final GenerationInfo[] infos = generateSetters(containingClass, options);
return infos != null && infos.length > 0 ? infos[0] : null;
}
@@ -58,11 +72,12 @@ public class PsiFieldMember extends PsiElementClassMember<PsiField> implements P
@Override
public GenerationInfo @Nullable [] generateSetters(PsiClass aClass) {
return generateSetters(aClass, EnumSet.noneOf(Option.class));
if (aClass == null) return null;
return generateSetters(aClass, SetterGetterGenerationOptions.empty());
}
@Override
public GenerationInfo @Nullable [] generateSetters(PsiClass aClass, @NotNull EnumSet<Option> options) {
public GenerationInfo @Nullable [] generateSetters(@NotNull PsiClass aClass, @NotNull SetterGetterGenerationOptions options) {
final PsiField field = getElement();
if (GetterSetterPrototypeProvider.isReadOnlyProperty(field)) {
return null;
@@ -75,13 +90,13 @@ public class PsiFieldMember extends PsiElementClassMember<PsiField> implements P
for (PsiMethod prototype : prototypes) {
final PsiMethod method = createMethodIfNotExists(aClass, prototype);
if (method != null) {
methods.add(new PsiGenerationInfo(method));
methods.add(new PsiGenerationInfo<>(method));
}
}
return methods.isEmpty() ? null : methods.toArray(GenerationInfo.EMPTY_ARRAY);
}
private static @Nullable PsiMethod createMethodIfNotExists(PsiClass aClass, final PsiMethod template) {
private static @Nullable PsiMethod createMethodIfNotExists( @NotNull PsiClass aClass, final PsiMethod template) {
PsiMethod existing = aClass.findMethodBySignature(template, false);
return existing == null || !existing.isPhysical() ? template : null;
}

View File

@@ -0,0 +1,8 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.generation;
public record SetterGetterGenerationOptions(boolean copyAllAnnotations) {
public static SetterGetterGenerationOptions empty() {
return new SetterGetterGenerationOptions(false);
}
}

View File

@@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
public class GenerateGetterSetterTest extends LightJavaCodeInsightFixtureTestCase {
@@ -464,8 +463,8 @@ public class GenerateGetterSetterTest extends LightJavaCodeInsightFixtureTestCas
}
@Override
protected @NotNull EnumSet<EncapsulatableClassMember.Option> getOptions() {
return allAnnotations ? EnumSet.of(EncapsulatableClassMember.Option.COPY_ALL_ANNOTATIONS) : super.getOptions();
protected @NotNull SetterGetterGenerationOptions getOptions() {
return allAnnotations ? new SetterGetterGenerationOptions(true) : super.getOptions();
}
}.invoke(getProject(), myFixture.getEditor(), myFixture.getFile());
UIUtil.dispatchAllInvocationEvents();
@@ -564,8 +563,8 @@ public class GenerateGetterSetterTest extends LightJavaCodeInsightFixtureTestCas
}
@Override
protected @NotNull EnumSet<EncapsulatableClassMember.Option> getOptions() {
return allAnnotations ? EnumSet.of(EncapsulatableClassMember.Option.COPY_ALL_ANNOTATIONS) : super.getOptions();
protected @NotNull SetterGetterGenerationOptions getOptions() {
return allAnnotations ? new SetterGetterGenerationOptions(true) : super.getOptions();
}
}.invoke(getProject(), myFixture.getEditor(), myFixture.getFile());
UIUtil.dispatchAllInvocationEvents();

View File

@@ -1621,7 +1621,7 @@ generate.getter.error.no.fields=No fields have been found to generate getters fo
generate.getter.error.no.fields.without.getters=No fields without getter were found
generate.getter.setter.header.visibility.hint.=Visibility is applied according to File | Settings | Editor | Code Style | Java | Code Generation
generate.getter.setter.generate.all.annotations=Copy &all annotations
generate.getter.setter.generate.all.annotations.tooltip=Copy all annotations from fields. Otherwise, only nullable annotations will be copied
generate.getter.setter.generate.all.annotations.tooltip=Copy all applicable annotations from fields. Otherwise, only nullability annotations will be copied
generate.members.nothing.to.insert=Nothing found to insert
generate.setters.no.fields=No fields have been found to generate setters for
generate.setters.no.fields.without.setters=No fields without setter were found