From 7ffa9bd6ca575cd3584acb234ec8414f983f435f Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Mon, 21 Nov 2016 10:55:41 +0100 Subject: [PATCH] override/implement annotation settings (IDEA-58379) annotations are removed by default for both return and parameters, custom OverrideImplementHandlers can provide predefined annotations which must be repeat in overriders, custom annotations can be configured by the user --- .../CodeStyleGenerationConfigurable.form | 63 ++++++++------ .../CodeStyleGenerationConfigurable.java | 23 +++++- .../GenerateConstructorHandler.java | 5 +- .../generation/GenerateMembersUtil.java | 56 +++---------- .../generation/OverrideImplementUtil.java | 24 +----- .../OverrideImplementsAnnotationsHandler.java | 44 +++++++++- ...rrideImplementsAnnotationsHandlerImpl.java | 24 ++---- .../util/SpecialAnnotationsUtil.java | 19 +++-- .../generateEquals/afterArrays.java | 8 +- .../generateEquals/afterArraysClass.java | 6 +- .../generateEquals/afterInsertOverride.java | 4 +- .../generateEquals/afterLangClass.java | 4 +- .../generateEquals/afterLocalLangClass.java | 4 +- .../codeInsight/GenerateEqualsTest.java | 22 +++-- .../codeInsight/OverrideImplementTest.groovy | 82 +++++++++++++++++++ .../psi/codeStyle/CodeStyleSettings.java | 29 ++++++- ...ideImplementsTestNGAnnotationsHandler.java | 10 +-- 17 files changed, 273 insertions(+), 154 deletions(-) diff --git a/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.form b/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.form index 982b4f501bb1..2a78a5c91c21 100644 --- a/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.form +++ b/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.form @@ -15,7 +15,7 @@ - + @@ -179,21 +179,9 @@ - + - - - - - - - - - - - - @@ -227,16 +215,15 @@ - + - - + - + @@ -247,6 +234,7 @@ + @@ -255,6 +243,7 @@ + @@ -262,19 +251,41 @@ - + + - + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.java b/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.java index df7f774d408a..ad77e8dc490a 100644 --- a/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.java +++ b/java/java-impl/src/com/intellij/application/options/CodeStyleGenerationConfigurable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,19 +17,24 @@ package com.intellij.application.options; import com.intellij.application.options.codeStyle.CommenterForm; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; +import com.intellij.codeInspection.util.SpecialAnnotationsUtil; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiClass; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.ui.JavaVisibilityPanel; import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.SortedListModel; import com.intellij.ui.ToolbarDecorator; import com.intellij.ui.components.JBList; +import com.intellij.util.ui.JBInsets; import javax.swing.*; import java.awt.*; @@ -62,7 +67,9 @@ public class CodeStyleGenerationConfigurable implements Configurable { private JPanel myVisibilityPanel; @SuppressWarnings("unused") private JPanel myCommenterPanel; + private JPanel myOverridePanel; private CommenterForm myCommenterForm; + private SortedListModel myRepeatAnnotationsModel; public CodeStyleGenerationConfigurable(CodeStyleSettings settings) { mySettings = settings; @@ -76,6 +83,13 @@ public class CodeStyleGenerationConfigurable implements Configurable { .disableAddAction().disableRemoveAction().createPanel(); myMembersPanel.add(panel, BorderLayout.CENTER); myVisibilityPanel.add(myJavaVisibilityPanel, BorderLayout.CENTER); + GridBagConstraints gc = + new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 1, GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH, + new JBInsets(0, 0, 0, 0), 0, 0); + final Condition isApplicable = aClass -> aClass.isAnnotationType(); + //noinspection Convert2Diamond + myRepeatAnnotationsModel = new SortedListModel(Comparator.naturalOrder()); + myOverridePanel.add(SpecialAnnotationsUtil.createSpecialAnnotationsListControl("Annotations to Repeat", false, isApplicable, myRepeatAnnotationsModel), gc); return myPanel; } @@ -111,7 +125,9 @@ public class CodeStyleGenerationConfigurable implements Configurable { myInsertOverrideAnnotationCheckBox.setSelected(settings.INSERT_OVERRIDE_ANNOTATION); myRepeatSynchronizedCheckBox.setSelected(settings.REPEAT_SYNCHRONIZED); myJavaVisibilityPanel.setVisibility(settings.VISIBILITY); - + + myRepeatAnnotationsModel.clear(); + myRepeatAnnotationsModel.addAll(settings.getRepeatAnnotations()); myCommenterForm.reset(settings); } @@ -144,6 +160,7 @@ public class CodeStyleGenerationConfigurable implements Configurable { myMembersOrderList.apply(settings); myCommenterForm.apply(settings); + settings.setRepeatAnnotations(myRepeatAnnotationsModel.getItems()); for (Project project : ProjectManager.getInstance().getOpenProjects()) { DaemonCodeAnalyzer.getInstance(project).settingsChanged(); @@ -188,6 +205,8 @@ public class CodeStyleGenerationConfigurable implements Configurable { isModified |= myCommenterForm.isModified(settings); + isModified |= !myRepeatAnnotationsModel.getItems().equals(settings.getRepeatAnnotations()); + return isModified; } diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java index 42de5fea9850..be0fcadea2eb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,6 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -251,7 +250,7 @@ public class GenerateConstructorHandler extends GenerateMembersHandlerBase { String name = param.getName(); assert name != null : param; PsiParameter newParam = factory.createParameter(name, param.getType(), aClass); - GenerateMembersUtil.copyOrReplaceModifierList(param, newParam); + GenerateMembersUtil.copyOrReplaceModifierList(param, aClass, newParam); constructor.getParameterList().add(newParam); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java index 1c3b41c04da4..eed904175819 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,8 +15,6 @@ */ package com.intellij.codeInsight.generation; -import com.intellij.codeInsight.AnnotationTargetUtil; -import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.ExceptionUtil; import com.intellij.codeInsight.NullableNotNullManager; import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils; @@ -26,13 +24,8 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.ScrollType; -import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.*; @@ -405,7 +398,7 @@ public class GenerateMembersUtil { final PsiParameter[] newParameters = overriddenParameters(parameters, factory, codeStyleManager, substitutor, target); for (int i = 0; i < newParameters.length; i++) { final PsiParameter newParameter = newParameters[i]; - copyOrReplaceModifierList(parameters[i], newParameter); + copyOrReplaceModifierList(parameters[i], target, newParameter); targetParameterList.add(newParameter); } } @@ -566,51 +559,24 @@ public class GenerateMembersUtil { OverrideImplementUtil.annotateOnOverrideImplement(method, base, overridden); } + /** + * to be deleted in 2017.2 + */ + @Deprecated public static void copyOrReplaceModifierList(@NotNull PsiModifierListOwner sourceParam, @NotNull PsiModifierListOwner targetParam) { + copyOrReplaceModifierList(sourceParam, null, targetParam); + } + + public static void copyOrReplaceModifierList(@NotNull PsiModifierListOwner sourceParam, @Nullable PsiElement targetClass, @NotNull PsiModifierListOwner targetParam) { PsiModifierList sourceModifierList = sourceParam.getModifierList(); PsiModifierList targetModifierList = targetParam.getModifierList(); if (sourceModifierList != null && targetModifierList != null) { - final Module module = ModuleUtilCore.findModuleForPsiElement(targetModifierList); - final GlobalSearchScope moduleScope = module != null ? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module) : null; - final Project project = targetModifierList.getProject(); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); - JVMElementFactory factory = JVMElementFactories.requireFactory(targetParam.getLanguage(), targetParam.getProject()); - for (PsiAnnotation annotation : AnnotationUtil.getAllAnnotations(sourceParam, false, null, false)) { - final String qualifiedName = annotation.getQualifiedName(); - if (qualifiedName != null && (moduleScope == null || facade.findClass(qualifiedName, moduleScope) != null) && - !AnnotationTargetUtil.isTypeAnnotation(annotation)) { - targetModifierList.add(factory.createAnnotationFromText(annotation.getText(), sourceParam)); - } - } for (@PsiModifier.ModifierConstant String m : PsiModifier.MODIFIERS) { targetModifierList.setModifierProperty(m, sourceParam.hasModifierProperty(m)); } - filterAnnotations(sourceModifierList.getProject(), targetModifierList, targetModifierList.getResolveScope()); - } - } - - private static void filterAnnotations(Project project, PsiModifierList modifierList, GlobalSearchScope moduleScope) { - Set toRemove = new HashSet<>(); - JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); - for (PsiAnnotation annotation : modifierList.getAnnotations()) { - String qualifiedName = annotation.getQualifiedName(); - if (qualifiedName != null) { - for (OverrideImplementsAnnotationsHandler handler : Extensions.getExtensions(OverrideImplementsAnnotationsHandler.EP_NAME)) { - String[] annotations2Remove = handler.annotationsToRemove(project, qualifiedName); - Collections.addAll(toRemove, annotations2Remove); - if (moduleScope != null && psiFacade.findClass(qualifiedName, moduleScope) == null) { - toRemove.add(qualifiedName); - } - } - } - } - for (String fqn : toRemove) { - PsiAnnotation psiAnnotation = modifierList.findAnnotation(fqn); - if (psiAnnotation != null) { - psiAnnotation.delete(); - } + OverrideImplementsAnnotationsHandler.repeatAnnotationsFromSource(sourceParam, targetClass, targetParam); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java index 0659c00a7673..0ee8e9323b88 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,8 +45,6 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapManager; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; @@ -58,7 +56,6 @@ import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.javadoc.PsiDocComment; -import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.*; import com.intellij.util.Consumer; import com.intellij.util.IncorrectOperationException; @@ -246,24 +243,7 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil { AddAnnotationPsiFix.addPhysicalAnnotation(overrideAnnotationName, PsiNameValuePair.EMPTY_ARRAY, method.getModifierList()); } } - final Module module = ModuleUtilCore.findModuleForPsiElement(targetClass); - final GlobalSearchScope moduleScope = module != null ? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module) : null; - final Project project = targetClass.getProject(); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); - for (OverrideImplementsAnnotationsHandler each : Extensions.getExtensions(OverrideImplementsAnnotationsHandler.EP_NAME)) { - for (String annotation : each.getAnnotations(project)) { - if (moduleScope != null && facade.findClass(annotation, moduleScope) == null) continue; - if (AnnotationUtil.isAnnotated(overridden, annotation, false, false) && !AnnotationUtil.isAnnotated(method, annotation, false, false)) { - PsiAnnotation psiAnnotation = AnnotationUtil.findAnnotation(overridden, annotation); - if (psiAnnotation != null && AnnotationUtil.isInferredAnnotation(psiAnnotation)) { - continue; - } - - AddAnnotationPsiFix.removePhysicalAnnotations(method, each.annotationsToRemove(project, annotation)); - AddAnnotationPsiFix.addPhysicalAnnotation(annotation, PsiNameValuePair.EMPTY_ARRAY, method.getModifierList()); - } - } - } + OverrideImplementsAnnotationsHandler.repeatAnnotationsFromSource(overridden, targetClass, method); } public static void annotate(@NotNull PsiMethod result, String fqn, String... annosToRemove) throws IncorrectOperationException { diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementsAnnotationsHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementsAnnotationsHandler.java index b69f53b762ea..497d84d23014 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementsAnnotationsHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementsAnnotationsHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,14 +20,54 @@ */ package com.intellij.codeInsight.generation; +import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.codeInsight.intention.AddAnnotationPsiFix; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface OverrideImplementsAnnotationsHandler { ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.overrideImplementsAnnotationsHandler"); + /** + * By default no annotations from source method return type and parameters are repeated. + * + * Return annotations which should be copied from the source to the implementation. + */ String[] getAnnotations(Project project); + + @Deprecated @NotNull - String [] annotationsToRemove(Project project, @NotNull String fqName); + default String [] annotationsToRemove(Project project, @NotNull String fqName) { + return ArrayUtil.EMPTY_STRING_ARRAY; + } + + static void repeatAnnotationsFromSource(PsiModifierListOwner source, @Nullable PsiElement targetClass, PsiModifierListOwner target) { + final Module module = ModuleUtilCore.findModuleForPsiElement(targetClass != null ? targetClass : target); + final GlobalSearchScope moduleScope = module != null ? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module) : null; + final Project project = target.getProject(); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + for (OverrideImplementsAnnotationsHandler each : Extensions.getExtensions(EP_NAME)) { + for (String annotation : each.getAnnotations(project)) { + if (moduleScope != null && facade.findClass(annotation, moduleScope) == null) continue; + if (AnnotationUtil.isAnnotated(source, annotation, false, false) && + !AnnotationUtil.isAnnotated(target, annotation, false, false)) { + + PsiAnnotation psiAnnotation = AnnotationUtil.findAnnotation(source, annotation); + if (psiAnnotation != null && AnnotationUtil.isInferredAnnotation(psiAnnotation)) { + continue; + } + + AddAnnotationPsiFix.addPhysicalAnnotation(annotation, PsiNameValuePair.EMPTY_ARRAY, target.getModifierList()); + } + } + } + } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementsAnnotationsHandlerImpl.java b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementsAnnotationsHandlerImpl.java index 5c55bdc702b6..848cabda2b69 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementsAnnotationsHandlerImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementsAnnotationsHandlerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,9 +23,9 @@ package com.intellij.codeInsight.generation; import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.NullableNotNullManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.util.ArrayUtil; -import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; @@ -37,22 +37,8 @@ public class OverrideImplementsAnnotationsHandlerImpl implements OverrideImpleme final Collection anns = new ArrayList<>(manager.getNotNulls()); anns.addAll(manager.getNullables()); anns.add(AnnotationUtil.NLS); + final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(project); + anns.addAll(settings.getRepeatAnnotations()); return ArrayUtil.toStringArray(anns); } - - @Override - @NotNull - public String[] annotationsToRemove(Project project, @NotNull final String fqName) { - final NullableNotNullManager manager = NullableNotNullManager.getInstance(project); - if (manager.getNotNulls().contains(fqName)) { - return ArrayUtil.toStringArray(manager.getNullables()); - } - if (manager.getNullables().contains(fqName)) { - return ArrayUtil.toStringArray(manager.getNotNulls()); - } - if (Comparing.strEqual(fqName, AnnotationUtil.NLS)){ - return new String[]{AnnotationUtil.NON_NLS}; - } - return ArrayUtil.EMPTY_STRING_ARRAY; - } } diff --git a/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java b/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java index 65ab2dd9c422..479e1e87f30a 100644 --- a/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java +++ b/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ import javax.swing.*; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import java.awt.*; +import java.util.Comparator; import java.util.List; /** @@ -62,13 +63,12 @@ public class SpecialAnnotationsUtil { final String borderTitle, final boolean acceptPatterns, final Condition isApplicable) { - final SortedListModel listModel = new SortedListModel<>((o1, o2) -> o1.compareTo(o2)); - final JList injectionList = new JBList(listModel); + @SuppressWarnings("Convert2Diamond") + SortedListModel listModel = new SortedListModel(Comparator.naturalOrder()); for (String s : list) { listModel.add(s); } - injectionList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); - injectionList.getModel().addListDataListener(new ListDataListener() { + listModel.addListDataListener(new ListDataListener() { @Override public void intervalAdded(ListDataEvent e) { listChanged(); @@ -91,7 +91,16 @@ public class SpecialAnnotationsUtil { listChanged(); } }); + return createSpecialAnnotationsListControl(borderTitle, acceptPatterns, isApplicable, listModel); + } + public static JPanel createSpecialAnnotationsListControl(final String borderTitle, + final boolean acceptPatterns, + final Condition isApplicable, + final SortedListModel listModel) { + final JList injectionList = new JBList(listModel); + + injectionList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(injectionList) .setAddAction(new AnActionButtonRunnable() { @Override diff --git a/java/java-tests/testData/codeInsight/generateEquals/afterArrays.java b/java/java-tests/testData/codeInsight/generateEquals/afterArrays.java index 7133833be36d..28b8d4f503c8 100644 --- a/java/java-tests/testData/codeInsight/generateEquals/afterArrays.java +++ b/java/java-tests/testData/codeInsight/generateEquals/afterArrays.java @@ -13,16 +13,16 @@ class Test { // Probably incorrect - comparing Object[] arrays with Arrays.equals if (!Arrays.equals(myOs, test.myOs)) return false; - // Compare nested arrays - values of myIIs here + if (!Arrays.deepEquals(myIIs, test.myIIs)) return false; if (!Arrays.equals(myIs, test.myIs)) return false; return true; } public int hashCode() { - int result = myOs != null ? myOs.hashCode() : 0; - result = 31 * result + (myIIs != null ? myIIs.hashCode() : 0); - result = 31 * result + (myIs != null ? myIs.hashCode() : 0); + int result = Arrays.hashCode(myOs); + result = 31 * result + Arrays.deepHashCode(myIIs); + result = 31 * result + Arrays.hashCode(myIs); return result; } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/generateEquals/afterArraysClass.java b/java/java-tests/testData/codeInsight/generateEquals/afterArraysClass.java index 4a7dd991f958..4a8936e30b18 100644 --- a/java/java-tests/testData/codeInsight/generateEquals/afterArraysClass.java +++ b/java/java-tests/testData/codeInsight/generateEquals/afterArraysClass.java @@ -1,7 +1,7 @@ class Arrays { int[] i; - @java.lang.Override + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -13,8 +13,8 @@ class Arrays { return true; } - @java.lang.Override + @Override public int hashCode() { - return i != null ? i.hashCode() : 0; + return java.util.Arrays.hashCode(i); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/generateEquals/afterInsertOverride.java b/java/java-tests/testData/codeInsight/generateEquals/afterInsertOverride.java index 372962492e04..142a723a06e3 100644 --- a/java/java-tests/testData/codeInsight/generateEquals/afterInsertOverride.java +++ b/java/java-tests/testData/codeInsight/generateEquals/afterInsertOverride.java @@ -1,7 +1,7 @@ class Test { int i; - @java.lang.Override + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -13,7 +13,7 @@ class Test { return true; } - @java.lang.Override + @Override public int hashCode() { return i; } diff --git a/java/java-tests/testData/codeInsight/generateEquals/afterLangClass.java b/java/java-tests/testData/codeInsight/generateEquals/afterLangClass.java index d1d012191216..daf3edf8773b 100644 --- a/java/java-tests/testData/codeInsight/generateEquals/afterLangClass.java +++ b/java/java-tests/testData/codeInsight/generateEquals/afterLangClass.java @@ -1,7 +1,7 @@ class Integer { int i; - @java.lang.Override + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -13,7 +13,7 @@ class Integer { return true; } - @java.lang.Override + @Override public int hashCode() { return i; } diff --git a/java/java-tests/testData/codeInsight/generateEquals/afterLocalLangClass.java b/java/java-tests/testData/codeInsight/generateEquals/afterLocalLangClass.java index ec2ba28b64d7..2d604e430aa1 100644 --- a/java/java-tests/testData/codeInsight/generateEquals/afterLocalLangClass.java +++ b/java/java-tests/testData/codeInsight/generateEquals/afterLocalLangClass.java @@ -3,7 +3,7 @@ class Test { class Integer { int i; - @java.lang.Override + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -15,7 +15,7 @@ class Test { return true; } - @java.lang.Override + @Override public int hashCode() { return i; } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEqualsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEqualsTest.java index 60fbd7428679..6b6c5f1a3fa3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEqualsTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEqualsTest.java @@ -1,8 +1,20 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.testFramework.IdeaTestUtil; - /** * @author dsl */ @@ -67,8 +79,4 @@ public class GenerateEqualsTest extends GenerateEqualsTestCase { doTest(new int[]{0}, new int[]{0}, new int[0], true); } - @Override - protected Sdk getProjectJDK() { - return IdeaTestUtil.getMockJdk14(); - } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.groovy index 7dcce291905d..f0894813fed1 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.groovy @@ -17,9 +17,13 @@ package com.intellij.codeInsight import com.intellij.JavaTestUtil import com.intellij.codeInsight.generation.OverrideImplementUtil +import com.intellij.codeInsight.generation.OverrideImplementsAnnotationsHandler import com.intellij.idea.ActionsBundle import com.intellij.openapi.actionSystem.Presentation import com.intellij.openapi.command.CommandProcessor +import com.intellij.openapi.extensions.ExtensionPoint +import com.intellij.openapi.extensions.Extensions +import com.intellij.openapi.project.Project import com.intellij.psi.PsiClass import com.intellij.psi.util.PsiTreeUtil import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase @@ -217,6 +221,84 @@ class Test implements A { }""".stripIndent() } + void testCustomOverrideImplementsHandler() { + myFixture.addClass """package a; public @interface A { }""" + + myFixture.configureByText "test.java", """\ + import java.util.*; + import a.*; + + interface I { + @A List i(@A String p); + } + + class C implements I { + + }""".stripIndent() + + invokeAction(true) + + myFixture.checkResult """\ + import java.util.*; + import a.*; + + interface I { + @A List i(@A String p); + } + + class C implements I { + @Override + public List i(String p) { + return null; + } + }""".stripIndent() + + ExtensionPoint point = Extensions.getRootArea().getExtensionPoint(OverrideImplementsAnnotationsHandler.EP_NAME); + OverrideImplementsAnnotationsHandler extension = new OverrideImplementsAnnotationsHandler() { + @Override + String[] getAnnotations(Project project) { + return ["a.A"] + } + } + + try { + point.registerExtension(extension) + myFixture.configureByText "test.java", """\ + import java.util.*; + import a.*; + + interface I { + @A List i(@A String p); + } + + class C implements I { + + }""".stripIndent() + + invokeAction(true) + + myFixture.checkResult """\ + import java.util.*; + import a.*; + + interface I { + @A List i(@A String p); + } + + class C implements I { + @A + @Override + public List i(@A String p) { + return null; + } + }""".stripIndent() + + } + finally { + point.unregisterExtension(extension) + } + } + private void doTest(boolean toImplement) { String name = getTestName(false) myFixture.configureByFile("before${name}.java") diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java index 86783123c982..888798cf37e1 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java @@ -57,6 +57,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea private final UserDataHolder myUserDataHolder = new UserDataHolderBase(); + @NonNls private static final String REPEAT_ANNOTATIONS = "REPEAT_ANNOTATIONS"; @NonNls private static final String ADDITIONAL_INDENT_OPTIONS = "ADDITIONAL_INDENT_OPTIONS"; @NonNls private static final String FILETYPE = "fileType"; @@ -255,7 +256,18 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea //----------------- override ------------------- public boolean REPEAT_SYNCHRONIZED = true; -//----------------- IMPORTS -------------------- + private List myRepeatAnnotations = new ArrayList<>(); + + public List getRepeatAnnotations() { + return myRepeatAnnotations; + } + + public void setRepeatAnnotations(List repeatAnnotations) { + myRepeatAnnotations.clear(); + myRepeatAnnotations.addAll(repeatAnnotations); + } + + //----------------- IMPORTS -------------------- public boolean LAYOUT_STATIC_IMPORTS_SEPARATELY = true; public boolean USE_FQ_CLASS_NAMES; @@ -507,6 +519,14 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea } } + myRepeatAnnotations.clear(); + Element annotations = element.getChild(REPEAT_ANNOTATIONS); + if (annotations != null) { + for (Element anno : annotations.getChildren("ANNO")) { + myRepeatAnnotations.add(anno.getAttributeValue("name")); + } + } + UnknownElementCollector unknownElementCollector = new UnknownElementCollector(); for (CustomCodeStyleSettings settings : getCustomSettingsValues()) { settings.getKnownTagNames().forEach(unknownElementCollector::addKnownName); @@ -568,6 +588,13 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea } myCommonSettingsManager.writeExternal(element); + if (!myRepeatAnnotations.isEmpty()) { + Element annos = new Element(REPEAT_ANNOTATIONS); + for (String annotation : myRepeatAnnotations) { + annos.addContent(new Element("ANNO").setAttribute("name", annotation)); + } + element.addContent(annos); + } } private static IndentOptions getDefaultIndentOptions(FileType fileType) { diff --git a/plugins/testng/src/com/theoryinpractice/testng/intention/OverrideImplementsTestNGAnnotationsHandler.java b/plugins/testng/src/com/theoryinpractice/testng/intention/OverrideImplementsTestNGAnnotationsHandler.java index d0eb0b03db50..58ed289d54e2 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/intention/OverrideImplementsTestNGAnnotationsHandler.java +++ b/plugins/testng/src/com/theoryinpractice/testng/intention/OverrideImplementsTestNGAnnotationsHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,18 +22,10 @@ package com.theoryinpractice.testng.intention; import com.intellij.codeInsight.generation.OverrideImplementsAnnotationsHandler; import com.intellij.openapi.project.Project; -import com.intellij.util.ArrayUtil; import com.theoryinpractice.testng.util.TestNGUtil; -import org.jetbrains.annotations.NotNull; public class OverrideImplementsTestNGAnnotationsHandler implements OverrideImplementsAnnotationsHandler{ public String[] getAnnotations(Project project) { return TestNGUtil.CONFIG_ANNOTATIONS_FQN; } - - - @NotNull - public String[] annotationsToRemove(Project project, @NotNull final String fqName) { - return ArrayUtil.EMPTY_STRING_ARRAY; - } } \ No newline at end of file