|
14 | 14 | *******************************************************************************/ |
15 | 15 | package org.eclipse.jdt.ui.tests.core; |
16 | 16 |
|
| 17 | +import static org.eclipse.jdt.internal.corext.fix.CleanUpConstants.ORGANIZE_IMPORTS; |
| 18 | +import static org.eclipse.jdt.internal.corext.fix.CleanUpPreferenceUtilCore.SAVE_PARTICIPANT_KEY_PREFIX; |
| 19 | +import static org.eclipse.jdt.internal.ui.javaeditor.saveparticipant.SaveParticipantPreferenceConfigurationConstants.EDITOR_SAVE_PARTICIPANT_PREFIX; |
| 20 | +import static org.eclipse.jdt.internal.ui.javaeditor.saveparticipant.SaveParticipantPreferenceConfigurationConstants.POSTSAVELISTENER_ID; |
17 | 21 | import static org.junit.Assert.assertEquals; |
18 | 22 | import static org.junit.Assert.assertNotNull; |
19 | 23 | import static org.junit.Assert.assertTrue; |
20 | 24 |
|
21 | 25 | import java.io.File; |
| 26 | +import java.lang.reflect.Field; |
| 27 | +import java.util.ArrayList; |
22 | 28 | import java.util.Hashtable; |
| 29 | +import java.util.List; |
23 | 30 |
|
24 | 31 | import org.junit.After; |
25 | 32 | import org.junit.Before; |
|
30 | 37 | import org.eclipse.jdt.testplugin.JavaTestPlugin; |
31 | 38 | import org.eclipse.jdt.testplugin.TestOptions; |
32 | 39 |
|
| 40 | +import org.eclipse.core.runtime.NullProgressMonitor; |
33 | 41 | import org.eclipse.core.runtime.Path; |
34 | 42 | import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
| 43 | +import org.eclipse.core.runtime.preferences.InstanceScope; |
35 | 44 |
|
36 | 45 | import org.eclipse.core.resources.ProjectScope; |
37 | 46 |
|
38 | 47 | import org.eclipse.jface.preference.IPreferenceStore; |
39 | 48 |
|
| 49 | +import org.eclipse.ui.IEditorPart; |
| 50 | + |
40 | 51 | import org.eclipse.jdt.core.IClasspathAttribute; |
41 | 52 | import org.eclipse.jdt.core.ICompilationUnit; |
42 | 53 | import org.eclipse.jdt.core.IImportDeclaration; |
43 | 54 | import org.eclipse.jdt.core.IJavaProject; |
44 | 55 | import org.eclipse.jdt.core.IPackageFragment; |
45 | 56 | import org.eclipse.jdt.core.IPackageFragmentRoot; |
46 | 57 | import org.eclipse.jdt.core.JavaCore; |
| 58 | +import org.eclipse.jdt.core.JavaModelException; |
47 | 59 | import org.eclipse.jdt.core.Signature; |
48 | 60 | import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; |
49 | 61 | import org.eclipse.jdt.core.manipulation.OrganizeImportsOperation; |
50 | 62 | import org.eclipse.jdt.core.manipulation.OrganizeImportsOperation.IChooseImportQuery; |
| 63 | +import org.eclipse.jdt.core.search.IJavaSearchConstants; |
| 64 | +import org.eclipse.jdt.core.search.IJavaSearchScope; |
| 65 | +import org.eclipse.jdt.core.search.MethodNameMatch; |
| 66 | +import org.eclipse.jdt.core.search.MethodNameMatchRequestor; |
| 67 | +import org.eclipse.jdt.core.search.SearchEngine; |
| 68 | +import org.eclipse.jdt.core.search.SearchPattern; |
51 | 69 | import org.eclipse.jdt.core.search.TypeNameMatch; |
52 | 70 |
|
| 71 | +import org.eclipse.jdt.internal.core.CompilationUnit; |
| 72 | +import org.eclipse.jdt.internal.core.CompilationUnitElementInfo; |
| 73 | + |
53 | 74 | import org.eclipse.jdt.ui.JavaUI; |
54 | 75 | import org.eclipse.jdt.ui.PreferenceConstants; |
55 | 76 | import org.eclipse.jdt.ui.tests.core.rules.ProjectTestSetup; |
56 | 77 |
|
| 78 | +import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; |
| 79 | + |
57 | 80 | public class ImportOrganizeTest extends CoreTests { |
58 | 81 |
|
59 | 82 | private IJavaProject fJProject1; |
@@ -3880,6 +3903,158 @@ public class C1 { |
3880 | 3903 | """; |
3881 | 3904 | assertEqualString(cu1.getSource(), str2); |
3882 | 3905 | } |
| 3906 | + |
| 3907 | + @Test |
| 3908 | + public void testBug3918() throws Exception { |
| 3909 | + IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(JavaUI.ID_PLUGIN); |
| 3910 | + String postSaveActionsKey = EDITOR_SAVE_PARTICIPANT_PREFIX + POSTSAVELISTENER_ID; |
| 3911 | + String organizeImportsKey = SAVE_PARTICIPANT_KEY_PREFIX + ORGANIZE_IMPORTS; |
| 3912 | + |
| 3913 | + final boolean orgImportsOrigState = prefs.getBoolean(organizeImportsKey, false); |
| 3914 | + final boolean postSaveActionsOrigState = prefs.getBoolean(postSaveActionsKey, false); |
| 3915 | + |
| 3916 | + try { |
| 3917 | + prefs.putBoolean(postSaveActionsKey, true); |
| 3918 | + prefs.putBoolean(organizeImportsKey, true); |
| 3919 | + |
| 3920 | + IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src"); |
| 3921 | + |
| 3922 | + IPackageFragment pack0= sourceFolder.createPackageFragment("p", false, null); |
| 3923 | + String original= """ |
| 3924 | + package p; |
| 3925 | +
|
| 3926 | + import java.util.function.IntPredicate; |
| 3927 | + import java.util.Properties; |
| 3928 | +
|
| 3929 | + class UnusedStaticImport { |
| 3930 | + boolean value = match(Character::isUpperCase, 'A'); |
| 3931 | +
|
| 3932 | + public static boolean match(IntPredicate matcher, int codePoint) { |
| 3933 | + return matcher.test(codePoint); |
| 3934 | + } |
| 3935 | + } |
| 3936 | + """; |
| 3937 | + CompilationUnit icu= (CompilationUnit) pack0.createCompilationUnit("Unusedmport.java", original, false, null); |
| 3938 | + IEditorPart editor= EditorUtility.openInEditor(icu); |
| 3939 | + |
| 3940 | + long timeStamp= getElementInfoTimestamp(icu); |
| 3941 | + assertEquals("ICU modification stamp differs from resource stamp", icu.getResource().getModificationStamp(), timeStamp); |
| 3942 | + |
| 3943 | + // On save "organize imports" participant modifies CU and the CU timestamp should change. |
| 3944 | + // Check that CU stamp is still in-sync with the underlined IFie stamp |
| 3945 | + editor.doSave(new NullProgressMonitor()); |
| 3946 | + |
| 3947 | + String fixed= """ |
| 3948 | + package p; |
| 3949 | +
|
| 3950 | + import java.util.function.IntPredicate; |
| 3951 | +
|
| 3952 | + class UnusedStaticImport { |
| 3953 | + boolean value = match(Character::isUpperCase, 'A'); |
| 3954 | +
|
| 3955 | + public static boolean match(IntPredicate matcher, int codePoint) { |
| 3956 | + return matcher.test(codePoint); |
| 3957 | + } |
| 3958 | + } |
| 3959 | + """; |
| 3960 | + assertEqualString(fixed, icu.getSource()); |
| 3961 | + |
| 3962 | + timeStamp= getElementInfoTimestamp(icu); |
| 3963 | + assertEquals("ICU modification stamp differs from resource stamp", icu.getResource().getModificationStamp(), timeStamp); |
| 3964 | + } finally { |
| 3965 | + prefs.putBoolean(postSaveActionsKey, postSaveActionsOrigState); |
| 3966 | + prefs.putBoolean(organizeImportsKey, orgImportsOrigState); |
| 3967 | + } |
| 3968 | + } |
| 3969 | + |
| 3970 | + @Test |
| 3971 | + public void testBug3918_Search() throws Exception { |
| 3972 | + String postSaveActionsKey = EDITOR_SAVE_PARTICIPANT_PREFIX + POSTSAVELISTENER_ID; |
| 3973 | + String organizeImportsKey= SAVE_PARTICIPANT_KEY_PREFIX + ORGANIZE_IMPORTS; |
| 3974 | + IEclipsePreferences jdtUiPreferences = InstanceScope.INSTANCE.getNode(JavaUI.ID_PLUGIN); |
| 3975 | + final boolean orgImportsOrigState= jdtUiPreferences.getBoolean(organizeImportsKey, false); |
| 3976 | + final boolean postSaveActionsOrigState = jdtUiPreferences.getBoolean(postSaveActionsKey, false); |
| 3977 | + |
| 3978 | + try { |
| 3979 | + jdtUiPreferences.putBoolean(postSaveActionsKey, true); |
| 3980 | + jdtUiPreferences.putBoolean(organizeImportsKey, true); |
| 3981 | + |
| 3982 | + IPackageFragmentRoot sourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src"); |
| 3983 | + |
| 3984 | + IPackageFragment pack0= sourceFolder.createPackageFragment("p", false, null); |
| 3985 | + String original= """ |
| 3986 | + package p; |
| 3987 | +
|
| 3988 | + import java.util.function.IntPredicate; |
| 3989 | + import java.util.Properties; |
| 3990 | +
|
| 3991 | + class UnusedStaticImport { |
| 3992 | + boolean value = match(Character::isUpperCase, 'A'); |
| 3993 | +
|
| 3994 | + public static boolean match(IntPredicate matcher, int codePoint) { |
| 3995 | + return matcher.test(codePoint); |
| 3996 | + } |
| 3997 | + } |
| 3998 | + """; |
| 3999 | + ICompilationUnit icu= pack0.createCompilationUnit("Unusedmport.java", original, false, null); |
| 4000 | + IEditorPart editor= EditorUtility.openInEditor(icu); |
| 4001 | + class Collector extends MethodNameMatchRequestor { |
| 4002 | + List<MethodNameMatch> matches = new ArrayList<>(); |
| 4003 | + @Override |
| 4004 | + public void acceptMethodNameMatch(MethodNameMatch match) { |
| 4005 | + this.matches.add(match); |
| 4006 | + } |
| 4007 | + } |
| 4008 | + IJavaSearchScope scope = SearchEngine.createHierarchyScope(icu.getType("UnusedStaticImport")); |
| 4009 | + Collector collector = new Collector(); |
| 4010 | + new SearchEngine().searchAllMethodNames( |
| 4011 | + null, SearchPattern.R_PREFIX_MATCH, //package |
| 4012 | + null, SearchPattern.R_PREFIX_MATCH, // declaring Qualification |
| 4013 | + null, SearchPattern.R_PREFIX_MATCH, // declaring SimpleType |
| 4014 | + "match".toCharArray(), SearchPattern.R_PREFIX_MATCH, |
| 4015 | + scope, collector, |
| 4016 | + IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null); |
| 4017 | + |
| 4018 | + assertEquals("Should find one method, but found: " + collector.matches, 1, collector.matches.size()); |
| 4019 | + MethodNameMatch actual= collector.matches.get(0); |
| 4020 | + assertEquals("Unexpected method found", "match", actual.getMethod().getElementName()); |
| 4021 | + |
| 4022 | + // On save "organize imports" participant modifies CU so the CU stamp should be properly updated. |
| 4023 | + // That has impact on search results: we don't see matches if CU stamp is out of sync with IFile stamp. |
| 4024 | + editor.doSave(new NullProgressMonitor()); |
| 4025 | + |
| 4026 | + collector = new Collector(); |
| 4027 | + new SearchEngine().searchAllMethodNames( |
| 4028 | + null, SearchPattern.R_PREFIX_MATCH, //package |
| 4029 | + null, SearchPattern.R_PREFIX_MATCH, // declaring Qualification |
| 4030 | + null, SearchPattern.R_PREFIX_MATCH, // declaring SimpleType |
| 4031 | + "match".toCharArray(), SearchPattern.R_PREFIX_MATCH, |
| 4032 | + scope, collector, |
| 4033 | + IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null); |
| 4034 | + |
| 4035 | + assertEquals("Should find one method, but found: " + collector.matches, 1, collector.matches.size()); |
| 4036 | + actual= collector.matches.get(0); |
| 4037 | + assertEquals("Unexpected method found", "match", actual.getMethod().getElementName()); |
| 4038 | + |
| 4039 | + } finally { |
| 4040 | + jdtUiPreferences.putBoolean(postSaveActionsKey, postSaveActionsOrigState); |
| 4041 | + jdtUiPreferences.putBoolean(organizeImportsKey, orgImportsOrigState); |
| 4042 | + } |
| 4043 | + } |
| 4044 | + |
| 4045 | + private long getElementInfoTimestamp(CompilationUnit icu) throws NoSuchFieldException, IllegalAccessException, JavaModelException { |
| 4046 | + CompilationUnitElementInfo elementInfo= (CompilationUnitElementInfo) icu.getElementInfo(); |
| 4047 | + |
| 4048 | + Field timestampField= CompilationUnitElementInfo.class.getDeclaredField("timestamp"); |
| 4049 | + long timeStamp; |
| 4050 | + try { |
| 4051 | + timestampField.setAccessible(true); |
| 4052 | + timeStamp= (long) timestampField.get(elementInfo); |
| 4053 | + } finally { |
| 4054 | + timestampField.setAccessible(false); |
| 4055 | + } |
| 4056 | + return timeStamp; |
| 4057 | + } |
3883 | 4058 |
|
3884 | 4059 | protected OrganizeImportsOperation createOperation(ICompilationUnit cu, String[] order, int threshold, boolean ignoreLowerCaseNames, boolean save, boolean allowSyntaxErrors, IChooseImportQuery chooseImportQuery) { |
3885 | 4060 | setOrganizeImportSettings(order, threshold, threshold, cu.getJavaProject()); |
|
0 commit comments