mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 22:51:17 +07:00
IJ-CR-144148 [java] IDEA-358751 Java Annotations copied to generated getter / setter
- add new option GitOrigin-RevId: b893b09e8e157cbcc4cba78cda4d61e973f1f4e5
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a8ca44f462
commit
8980aa2c1f
@@ -15,26 +15,55 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.generation;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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
|
||||
@Nullable
|
||||
GenerationInfo generateGetter() throws IncorrectOperationException;
|
||||
|
||||
/**
|
||||
* @return PsiElement or TemplateGenerationInfo
|
||||
* @deprecated please, use {@link EncapsulatableClassMember#generateSetter(EnumSet)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
GenerationInfo generateSetter() throws IncorrectOperationException;
|
||||
|
||||
/**
|
||||
* @return PsiElement or TemplateGenerationInfo
|
||||
*/
|
||||
@Nullable
|
||||
default GenerationInfo generateGetter(@NotNull EnumSet<Option> options) throws IncorrectOperationException {
|
||||
return generateGetter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PsiElement or TemplateGenerationInfo
|
||||
*/
|
||||
@Nullable
|
||||
default GenerationInfo generateSetter(@NotNull EnumSet<Option> options) throws IncorrectOperationException {
|
||||
return generateSetter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the member is definitely read-only (no setter could be generated); false if it's not known.
|
||||
*/
|
||||
default boolean isReadOnlyMember() {
|
||||
return false;
|
||||
}
|
||||
|
||||
enum Option {
|
||||
COPY_ALL_ANNOTATIONS
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ public class GenerateGetterAndSetterHandler extends GenerateGetterSetterHandlerB
|
||||
|
||||
@Override
|
||||
public GenerationInfo[] generateMemberPrototypes(PsiClass aClass, ClassMember original) throws IncorrectOperationException {
|
||||
myGenerateGetterHandler.myGenerateAnnotations = myGenerateAnnotations;
|
||||
myGenerateSetterHandler.myGenerateAnnotations = myGenerateAnnotations;
|
||||
ArrayList<GenerationInfo> array = new ArrayList<>();
|
||||
GenerationInfo[] getters = myGenerateGetterHandler.generateMemberPrototypes(aClass, original);
|
||||
GenerationInfo[] setters = myGenerateSetterHandler.generateMemberPrototypes(aClass, original);
|
||||
|
||||
@@ -35,12 +35,12 @@ public class GenerateGetterHandler extends GenerateGetterSetterHandlerBase {
|
||||
@Override
|
||||
protected GenerationInfo[] generateMemberPrototypes(PsiClass aClass, ClassMember original) throws IncorrectOperationException {
|
||||
if (original instanceof PropertyClassMember propertyClassMember) {
|
||||
final GenerationInfo[] getters = propertyClassMember.generateGetters(aClass);
|
||||
final GenerationInfo[] getters = propertyClassMember.generateGetters(aClass, getOptions());
|
||||
if (getters != null) {
|
||||
return getters;
|
||||
}
|
||||
} else if (original instanceof EncapsulatableClassMember encapsulatableClassMember) {
|
||||
final GenerationInfo getter = encapsulatableClassMember.generateGetter();
|
||||
final GenerationInfo getter = encapsulatableClassMember.generateGetter(getOptions());
|
||||
if (getter != null) {
|
||||
return new GenerationInfo[]{getter};
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.ui.SimpleListCellRenderer;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.indexing.DumbModeAccessType;
|
||||
@@ -30,11 +31,16 @@ 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 {
|
||||
private static final Logger LOG = Logger.getInstance(GenerateGetterSetterHandlerBase.class);
|
||||
|
||||
protected boolean myGenerateAnnotations;
|
||||
@Nullable
|
||||
private JBCheckBox myGenerateAnnotationsCheckBox;
|
||||
|
||||
public GenerateGetterSetterHandlerBase(@NlsContexts.DialogTitle String chooserTitle) {
|
||||
super(chooserTitle);
|
||||
}
|
||||
@@ -63,6 +69,33 @@ public abstract class GenerateGetterSetterHandlerBase extends GenerateMembersHan
|
||||
return chooseMembers(allMembers, false, false, project, editor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassMember @Nullable [] chooseMembers(ClassMember[] members,
|
||||
boolean allowEmptySelection,
|
||||
boolean copyJavadocCheckbox,
|
||||
Project project,
|
||||
@Nullable Editor editor) {
|
||||
ClassMember[] chosenMembers = super.chooseMembers(members, allowEmptySelection, copyJavadocCheckbox, project, editor);
|
||||
myGenerateAnnotations = myGenerateAnnotationsCheckBox != null && myGenerateAnnotationsCheckBox.isSelected();
|
||||
myGenerateAnnotationsCheckBox = null;
|
||||
return chosenMembers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent @Nullable [] getOptionControls() {
|
||||
if (myGenerateAnnotationsCheckBox == null) {
|
||||
myGenerateAnnotationsCheckBox = new JBCheckBox(JavaBundle.message("generate.getter.setter.generate.all.annotations"), false);
|
||||
myGenerateAnnotationsCheckBox.setToolTipText(JavaBundle.message("generate.getter.setter.generate.all.annotations.tooltip"));
|
||||
}
|
||||
return new JComponent[] {myGenerateAnnotationsCheckBox};
|
||||
}
|
||||
|
||||
protected @NotNull EnumSet<EncapsulatableClassMember.Option> getOptions() {
|
||||
return myGenerateAnnotations
|
||||
? EnumSet.of(EncapsulatableClassMember.Option.COPY_ALL_ANNOTATIONS)
|
||||
: EnumSet.noneOf(EncapsulatableClassMember.Option.class);
|
||||
}
|
||||
|
||||
protected static JComponent getHeaderPanel(final Project project, final TemplatesManager templatesManager, final @Nls String templatesTitle) {
|
||||
final JPanel panel = new JPanel(new BorderLayout());
|
||||
final JLabel templateChooserLabel = new JLabel(templatesTitle);
|
||||
|
||||
@@ -763,20 +763,29 @@ public final class GenerateMembersUtil {
|
||||
}
|
||||
|
||||
public static @NotNull PsiMethod generateSetterPrototype(@NotNull PsiField field, PsiClass aClass) {
|
||||
return generatePrototype(field, aClass, true, SetterTemplatesManager.getInstance());
|
||||
return generatePrototype(field, aClass, true, EnumSet.noneOf(EncapsulatableClassMember.Option.class), SetterTemplatesManager.getInstance());
|
||||
}
|
||||
|
||||
static @NotNull PsiMethod generateGetterPrototype(@NotNull PsiField field, boolean ignoreInvalidTemplate) {
|
||||
return generatePrototype(field, field.getContainingClass(), ignoreInvalidTemplate, GetterTemplatesManager.getInstance());
|
||||
return generateGetterPrototype(field, ignoreInvalidTemplate, EnumSet.noneOf(EncapsulatableClassMember.Option.class));
|
||||
}
|
||||
|
||||
static @NotNull PsiMethod generateSetterPrototype(@NotNull PsiField field, boolean ignoreInvalidTemplate) {
|
||||
return generatePrototype(field, field.getContainingClass(), ignoreInvalidTemplate, SetterTemplatesManager.getInstance());
|
||||
return generateSetterPrototype(field, ignoreInvalidTemplate, EnumSet.noneOf(EncapsulatableClassMember.Option.class));
|
||||
}
|
||||
|
||||
static @NotNull PsiMethod generateGetterPrototype(@NotNull PsiField field, boolean ignoreInvalidTemplate, @NotNull EnumSet<EncapsulatableClassMember.Option> options) {
|
||||
return generatePrototype(field, field.getContainingClass(), ignoreInvalidTemplate, options, GetterTemplatesManager.getInstance());
|
||||
}
|
||||
|
||||
static @NotNull PsiMethod generateSetterPrototype(@NotNull PsiField field, boolean ignoreInvalidTemplate, @NotNull EnumSet<EncapsulatableClassMember.Option> 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 TemplatesManager templatesManager) {
|
||||
Project project = field.getProject();
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
@@ -823,10 +832,92 @@ public final class GenerateMembersUtil {
|
||||
annotationTarget = parameters.length == 1 ? parameters[0] : null;
|
||||
}
|
||||
if (annotationTarget != null) {
|
||||
PsiType fieldType = field.getType();
|
||||
String type = options.contains(EncapsulatableClassMember.Option.COPY_ALL_ANNOTATIONS) ? fieldType.getCanonicalText(true) :
|
||||
getTypeWithNullableAnnotations(factory, fieldType);
|
||||
if (annotationTarget instanceof PsiParameter psiParameter && psiParameter.getTypeElement() != null) {
|
||||
psiParameter.getTypeElement().replace(factory.createTypeElementFromText(type, psiParameter));
|
||||
}
|
||||
else {
|
||||
PsiMethod psiMethod = (PsiMethod)annotationTarget;
|
||||
PsiTypeElement returnTypeElement = psiMethod.getReturnTypeElement();
|
||||
if (returnTypeElement != null) {
|
||||
returnTypeElement.replace(factory.createTypeElementFromText(type, psiMethod));
|
||||
}
|
||||
}
|
||||
NullableNotNullManager.getInstance(project).copyNullableOrNotNullAnnotation(field, annotationTarget);
|
||||
}
|
||||
|
||||
return generatePrototype(field, result);
|
||||
PsiMethod method = generatePrototype(field, result);
|
||||
PsiModifierList modifierList = method.getModifierList();
|
||||
PsiModifierList newList = ModifierListUtil.createSortedModifierList(modifierList, null, true);
|
||||
if (newList != null) {
|
||||
new CommentTracker().replace(modifierList, newList);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Let's keep only nullable annotations, otherwise it can bother users who use frameworks, especially Hibernate
|
||||
*/
|
||||
private static @NotNull String getTypeWithNullableAnnotations(PsiElementFactory factory, PsiType type) {
|
||||
PsiType copyType = factory.createTypeFromText(type.getCanonicalText(true), null);
|
||||
List<PsiAnnotation> annotationsToDelete = new ArrayList<>();
|
||||
PsiTypeVisitor<PsiType> visitor = new PsiTypeVisitor<>() {
|
||||
@Override
|
||||
public PsiType visitType(@NotNull PsiType type) {
|
||||
for (PsiAnnotation annotation : type.getAnnotations()) {
|
||||
if (!NullableNotNullManager.isNullabilityAnnotation(annotation)) {
|
||||
annotationsToDelete.add(annotation);
|
||||
}
|
||||
}
|
||||
return super.visitType(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitClassType(@NotNull PsiClassType classType) {
|
||||
for (PsiType parameter : classType.getParameters()) {
|
||||
parameter.accept(this);
|
||||
}
|
||||
return super.visitClassType(classType);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PsiType visitArrayType(@NotNull PsiArrayType arrayType) {
|
||||
arrayType.getComponentType().accept(this);
|
||||
return super.visitArrayType(arrayType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitWildcardType(@NotNull PsiWildcardType wildcardType) {
|
||||
if(wildcardType.getBound() != null) {
|
||||
wildcardType.getBound().accept(this);
|
||||
}
|
||||
return super.visitWildcardType(wildcardType) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitIntersectionType(@NotNull PsiIntersectionType intersectionType) {
|
||||
for (PsiType t1 : intersectionType.getConjuncts()) {
|
||||
t1.accept(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitDisjunctionType(@NotNull PsiDisjunctionType disjunctionType) {
|
||||
for (PsiType t1 : disjunctionType.getDisjunctions()) {
|
||||
t1.accept(this);
|
||||
}
|
||||
return super.visitDisjunctionType(disjunctionType);
|
||||
}
|
||||
};
|
||||
copyType.accept(visitor);
|
||||
for (PsiAnnotation annotation : annotationsToDelete) {
|
||||
annotation.delete();
|
||||
}
|
||||
return copyType.getCanonicalText(true);
|
||||
}
|
||||
|
||||
private static @NotNull PsiMethod generatePrototype(@NotNull PsiField field, @NotNull PsiMethod result) {
|
||||
|
||||
@@ -37,13 +37,13 @@ public class GenerateSetterHandler extends GenerateGetterSetterHandlerBase {
|
||||
@Override
|
||||
protected GenerationInfo[] generateMemberPrototypes(PsiClass aClass, ClassMember original) throws IncorrectOperationException {
|
||||
if (original instanceof PropertyClassMember propertyClassMember) {
|
||||
final GenerationInfo[] getters = propertyClassMember.generateSetters(aClass);
|
||||
final GenerationInfo[] getters = propertyClassMember.generateSetters(aClass, getOptions());
|
||||
if (getters != null) {
|
||||
return getters;
|
||||
}
|
||||
}
|
||||
else if (original instanceof EncapsulatableClassMember encapsulatableClassMember) {
|
||||
final GenerationInfo setter = encapsulatableClassMember.generateSetter();
|
||||
final GenerationInfo setter = encapsulatableClassMember.generateSetter(getOptions());
|
||||
if (setter != null) {
|
||||
return new GenerationInfo[]{setter};
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.util.PropertyUtilBase;
|
||||
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");
|
||||
@@ -41,13 +44,20 @@ public abstract class GetterSetterPrototypeProvider {
|
||||
public static PsiMethod[] generateGetterSetters(PsiField field,
|
||||
boolean generateGetter,
|
||||
boolean ignoreInvalidTemplate) {
|
||||
return generateGetterSetters(field, generateGetter, ignoreInvalidTemplate, EnumSet.noneOf(EncapsulatableClassMember.Option.class));
|
||||
}
|
||||
|
||||
public static PsiMethod[] generateGetterSetters(PsiField field,
|
||||
boolean generateGetter,
|
||||
boolean ignoreInvalidTemplate,
|
||||
@NotNull EnumSet<EncapsulatableClassMember.Option> options) {
|
||||
for (GetterSetterPrototypeProvider provider : EP_NAME.getExtensionList()) {
|
||||
if (provider.canGeneratePrototypeFor(field)) {
|
||||
return generateGetter ? provider.generateGetters(field) : provider.generateSetters(field);
|
||||
}
|
||||
}
|
||||
return new PsiMethod[]{generateGetter ? GenerateMembersUtil.generateGetterPrototype(field, ignoreInvalidTemplate) :
|
||||
GenerateMembersUtil.generateSetterPrototype(field, ignoreInvalidTemplate)};
|
||||
return new PsiMethod[]{generateGetter ? GenerateMembersUtil.generateGetterPrototype(field, ignoreInvalidTemplate, options) :
|
||||
GenerateMembersUtil.generateSetterPrototype(field, ignoreInvalidTemplate, options)};
|
||||
}
|
||||
|
||||
public static boolean isReadOnlyProperty(PsiField field) {
|
||||
|
||||
@@ -17,16 +17,37 @@ package com.intellij.codeInsight.generation;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
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
|
||||
GenerationInfo @Nullable [] generateGetters(PsiClass aClass) throws IncorrectOperationException;
|
||||
|
||||
/**
|
||||
* @return PsiElement or TemplateGenerationInfo
|
||||
* @deprecated please, use {@link PropertyClassMember#generateSetters(PsiClass, EnumSet)}
|
||||
*/
|
||||
@Deprecated
|
||||
GenerationInfo @Nullable [] generateSetters(PsiClass aClass) throws IncorrectOperationException;
|
||||
|
||||
/**
|
||||
* @return PsiElement or TemplateGenerationInfo
|
||||
*/
|
||||
default GenerationInfo @Nullable [] generateGetters(PsiClass aClass, @NotNull EnumSet<Option> options) throws IncorrectOperationException{
|
||||
return generateGetters(aClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PsiElement or TemplateGenerationInfo
|
||||
*/
|
||||
default GenerationInfo @Nullable [] generateSetters(PsiClass aClass, @NotNull EnumSet<Option> options) throws IncorrectOperationException{
|
||||
return generateSetters(aClass);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ 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 {
|
||||
@@ -30,12 +31,18 @@ public class PsiFieldMember extends PsiElementClassMember<PsiField> implements P
|
||||
|
||||
@Override
|
||||
public GenerationInfo @Nullable [] generateGetters(PsiClass aClass) throws IncorrectOperationException {
|
||||
return generateGetters(aClass, EnumSet.noneOf(Option.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenerationInfo @Nullable [] generateGetters(PsiClass aClass, @NotNull EnumSet<Option> options) throws IncorrectOperationException {
|
||||
PsiField field = getElement();
|
||||
if (field.hasModifierProperty(PsiModifier.STATIC) &&
|
||||
field.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return null;
|
||||
}
|
||||
return createGenerateInfos(aClass, GetterSetterPrototypeProvider.generateGetterSetters(field, true, false));
|
||||
return createGenerateInfos(aClass,
|
||||
GetterSetterPrototypeProvider.generateGetterSetters(field, true, false, options));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,11 +58,16 @@ public class PsiFieldMember extends PsiElementClassMember<PsiField> implements P
|
||||
|
||||
@Override
|
||||
public GenerationInfo @Nullable [] generateSetters(PsiClass aClass) {
|
||||
return generateSetters(aClass, EnumSet.noneOf(Option.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenerationInfo @Nullable [] generateSetters(PsiClass aClass, @NotNull EnumSet<Option> options) {
|
||||
final PsiField field = getElement();
|
||||
if (GetterSetterPrototypeProvider.isReadOnlyProperty(field)) {
|
||||
return null;
|
||||
}
|
||||
return createGenerateInfos(aClass, GetterSetterPrototypeProvider.generateGetterSetters(field, false, false));
|
||||
return createGenerateInfos(aClass, GetterSetterPrototypeProvider.generateGetterSetters(field, false, false, options));
|
||||
}
|
||||
|
||||
private static GenerationInfo[] createGenerateInfos(PsiClass aClass, PsiMethod[] prototypes) {
|
||||
|
||||
@@ -24,6 +24,7 @@ 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 {
|
||||
@@ -241,44 +242,46 @@ public class GenerateGetterSetterTest extends LightJavaCodeInsightFixtureTestCas
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Target({ElementType.TYPE_USE, ElementType.ANNOTATION_TYPE})
|
||||
public @interface NotNull {}""");
|
||||
myFixture.addClass("""
|
||||
package org.jetbrains.annotations;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Target({ElementType.TYPE_USE, ElementType.ANNOTATION_TYPE})
|
||||
public @interface Size {}""");
|
||||
myFixture.configureByText("a.java", """
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Size;
|
||||
|
||||
class Foo {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
@org.jetbrains.annotations.Size
|
||||
@NotNull
|
||||
@Size
|
||||
private String myName;
|
||||
|
||||
private List<@org.jetbrains.annotations.NotNull @org.jetbrains.annotations.Size String> parents;
|
||||
private List<? extends @org.jetbrains.annotations.NotNull @org.jetbrains.annotations.Size String> extParents;
|
||||
private @org.jetbrains.annotations.NotNull @org.jetbrains.annotations.Size String[] children;
|
||||
private List<@NotNull @Size String> parents;
|
||||
private List<? extends @NotNull @Size String> extParents;
|
||||
private @NotNull @Size String[] children;
|
||||
<caret>
|
||||
}
|
||||
""");
|
||||
generateGetter();
|
||||
generateSetter();
|
||||
myFixture.checkResult("""
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Size;
|
||||
|
||||
class Foo {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
@org.jetbrains.annotations.Size
|
||||
@NotNull
|
||||
@Size
|
||||
private String myName;
|
||||
|
||||
private List<@org.jetbrains.annotations.NotNull @org.jetbrains.annotations.Size String> parents;
|
||||
private List<? extends @org.jetbrains.annotations.NotNull @org.jetbrains.annotations.Size String> extParents;
|
||||
private @org.jetbrains.annotations.NotNull @org.jetbrains.annotations.Size String[] children;
|
||||
private List<@NotNull @Size String> parents;
|
||||
private List<? extends @NotNull @Size String> extParents;
|
||||
private @NotNull @Size String[] children;
|
||||
|
||||
public void setMyName(@NotNull String myName) {
|
||||
this.myName = myName;
|
||||
@@ -315,6 +318,88 @@ public class GenerateGetterSetterTest extends LightJavaCodeInsightFixtureTestCas
|
||||
""");
|
||||
}
|
||||
|
||||
public void testNullableStuffWithDifferentTypeUseAllAnnotations() {
|
||||
myFixture.addClass("""
|
||||
package org.jetbrains.annotations;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
public @interface NotNull {}""");
|
||||
myFixture.addClass("""
|
||||
package org.jetbrains.annotations;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
public @interface Size {}""");
|
||||
myFixture.configureByText("a.java", """
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Size;
|
||||
|
||||
class Foo {
|
||||
@NotNull
|
||||
@Size
|
||||
private String myName;
|
||||
|
||||
private List<@NotNull @Size String> parents;
|
||||
private List<? extends @NotNull @Size String> extParents;
|
||||
private @NotNull @Size String[] children;
|
||||
<caret>
|
||||
}
|
||||
""");
|
||||
generateGetter(true);
|
||||
generateSetter(true);
|
||||
myFixture.checkResult("""
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Size;
|
||||
|
||||
class Foo {
|
||||
@NotNull
|
||||
@Size
|
||||
private String myName;
|
||||
|
||||
private List<@NotNull @Size String> parents;
|
||||
private List<? extends @NotNull @Size String> extParents;
|
||||
private @NotNull @Size String[] children;
|
||||
|
||||
public void setMyName(@NotNull @Size String myName) {
|
||||
this.myName = myName;
|
||||
}
|
||||
|
||||
public void setParents(List<@NotNull @Size String> parents) {
|
||||
this.parents = parents;
|
||||
}
|
||||
|
||||
public void setExtParents(List<? extends @NotNull @Size String> extParents) {
|
||||
this.extParents = extParents;
|
||||
}
|
||||
|
||||
public void setChildren(@NotNull @Size String[] children) {
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
public @NotNull @Size String getMyName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public List<@NotNull @Size String> getParents() {
|
||||
return parents;
|
||||
}
|
||||
|
||||
public List<? extends @NotNull @Size String> getExtParents() {
|
||||
return extParents;
|
||||
}
|
||||
|
||||
public @NotNull @Size String[] getChildren() {
|
||||
return children;
|
||||
}
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
public void testLombokGeneratedFieldsWithoutContainingFile() {
|
||||
ServiceContainerUtil.registerExtension(ApplicationManager.getApplication(), GenerateAccessorProviderRegistrar.EP_NAME,
|
||||
new NotNullFunction<PsiClass, Collection<EncapsulatableClassMember>>() {
|
||||
@@ -364,6 +449,10 @@ public class GenerateGetterSetterTest extends LightJavaCodeInsightFixtureTestCas
|
||||
}
|
||||
|
||||
private void generateGetter() {
|
||||
generateGetter(false);
|
||||
}
|
||||
|
||||
private void generateGetter(boolean allAnnotations) {
|
||||
new GenerateGetterHandler() {
|
||||
@Override
|
||||
protected ClassMember[] chooseMembers(ClassMember[] members,
|
||||
@@ -373,6 +462,11 @@ public class GenerateGetterSetterTest extends LightJavaCodeInsightFixtureTestCas
|
||||
@Nullable Editor editor) {
|
||||
return members;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull EnumSet<EncapsulatableClassMember.Option> getOptions() {
|
||||
return allAnnotations ? EnumSet.of(EncapsulatableClassMember.Option.COPY_ALL_ANNOTATIONS) : super.getOptions();
|
||||
}
|
||||
}.invoke(getProject(), myFixture.getEditor(), myFixture.getFile());
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
}
|
||||
@@ -455,6 +549,10 @@ public class GenerateGetterSetterTest extends LightJavaCodeInsightFixtureTestCas
|
||||
}
|
||||
|
||||
private void generateSetter() {
|
||||
generateSetter(false);
|
||||
}
|
||||
|
||||
private void generateSetter(boolean allAnnotations) {
|
||||
new GenerateSetterHandler() {
|
||||
@Override
|
||||
protected ClassMember[] chooseMembers(ClassMember[] members,
|
||||
@@ -464,6 +562,11 @@ public class GenerateGetterSetterTest extends LightJavaCodeInsightFixtureTestCas
|
||||
@Nullable Editor editor) {
|
||||
return members;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull EnumSet<EncapsulatableClassMember.Option> getOptions() {
|
||||
return allAnnotations ? EnumSet.of(EncapsulatableClassMember.Option.COPY_ALL_ANNOTATIONS) : super.getOptions();
|
||||
}
|
||||
}.invoke(getProject(), myFixture.getEditor(), myFixture.getFile());
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
}
|
||||
|
||||
@@ -1620,6 +1620,8 @@ generate.getter.and.setter.error.no.fields.without.getters.and.setters=No fields
|
||||
generate.getter.error.no.fields=No fields have been found to generate getters for
|
||||
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.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
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.jetbrains.java.generate.element;
|
||||
|
||||
import com.intellij.codeInsight.NullableNotNullManager;
|
||||
import com.intellij.core.JavaPsiBundle;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
@@ -26,9 +25,6 @@ import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.java.generate.psi.PsiAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Factory for creating {@link FieldElement} or {@link ClassElement} objects.
|
||||
*/
|
||||
@@ -169,7 +165,7 @@ public final class ElementFactory {
|
||||
// type names
|
||||
element.setTypeName(PsiAdapter.getTypeClassName(type));
|
||||
element.setTypeQualifiedName(PsiAdapter.getTypeQualifiedClassName(type));
|
||||
element.setType(getTypeWithNullableAnnotations(factory, type));
|
||||
element.setType(type.getCanonicalText());
|
||||
|
||||
// arrays, collections and maps types
|
||||
if (PsiAdapter.isObjectArrayType(type)) {
|
||||
@@ -221,67 +217,4 @@ public final class ElementFactory {
|
||||
else if (modifiers.hasModifierProperty(PsiModifier.PRIVATE)) element.setModifierPrivate(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Let's keep only nullable annotations, otherwise it can bother users who use frameworks, especially Hibernate
|
||||
*/
|
||||
private static @NotNull String getTypeWithNullableAnnotations(PsiElementFactory factory, PsiType type) {
|
||||
PsiType copyType = factory.createTypeFromText(type.getCanonicalText(true), null);
|
||||
List<PsiAnnotation> annotationsToDelete = new ArrayList<>();
|
||||
PsiTypeVisitor<PsiType> visitor = new PsiTypeVisitor<>() {
|
||||
@Override
|
||||
public PsiType visitType(@NotNull PsiType type) {
|
||||
for (PsiAnnotation annotation : type.getAnnotations()) {
|
||||
if (!NullableNotNullManager.isNullabilityAnnotation(annotation)) {
|
||||
annotationsToDelete.add(annotation);
|
||||
}
|
||||
}
|
||||
return super.visitType(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitClassType(@NotNull PsiClassType classType) {
|
||||
for (PsiType parameter : classType.getParameters()) {
|
||||
parameter.accept(this);
|
||||
}
|
||||
return super.visitClassType(classType);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PsiType visitArrayType(@NotNull PsiArrayType arrayType) {
|
||||
arrayType.getComponentType().accept(this);
|
||||
return super.visitArrayType(arrayType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitWildcardType(@NotNull PsiWildcardType wildcardType) {
|
||||
if(wildcardType.getBound() != null) {
|
||||
wildcardType.getBound().accept(this);
|
||||
}
|
||||
return super.visitWildcardType(wildcardType) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitIntersectionType(@NotNull PsiIntersectionType intersectionType) {
|
||||
for (PsiType t1 : intersectionType.getConjuncts()) {
|
||||
t1.accept(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitDisjunctionType(@NotNull PsiDisjunctionType disjunctionType) {
|
||||
for (PsiType t1 : disjunctionType.getDisjunctions()) {
|
||||
t1.accept(this);
|
||||
}
|
||||
return super.visitDisjunctionType(disjunctionType);
|
||||
}
|
||||
};
|
||||
copyType.accept(visitor);
|
||||
for (PsiAnnotation annotation : annotationsToDelete) {
|
||||
annotation.delete();
|
||||
}
|
||||
return copyType.getCanonicalText(true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user