1+ /*******************************************************************************
2+ * Copyright (c) 2024 Vector Informatik GmbH and others.
3+ *
4+ * This program and the accompanying materials
5+ * are made available under the terms of the Eclipse Public License 2.0
6+ * which accompanies this distribution, and is available at
7+ * https://www.eclipse.org/legal/epl-2.0/
8+ *
9+ * SPDX-License-Identifier: EPL-2.0
10+ *
11+ * Contributors:
12+ * Vector Informatik GmbH - initial API and implementation
13+ *******************************************************************************/
14+ package org .eclipse .ui .editors .tests ;
15+
16+ import static org .hamcrest .MatcherAssert .assertThat ;
17+ import static org .hamcrest .Matchers .is ;
18+ import static org .junit .Assert .assertEquals ;
19+
20+ import java .util .ResourceBundle ;
21+
22+ import org .hamcrest .Matchers ;
23+ import org .junit .After ;
24+ import org .junit .Before ;
25+ import org .junit .Test ;
26+ import org .osgi .framework .FrameworkUtil ;
27+
28+ import org .eclipse .core .runtime .CoreException ;
29+
30+ import org .eclipse .core .resources .IFile ;
31+ import org .eclipse .core .resources .IProject ;
32+ import org .eclipse .core .resources .IResource ;
33+ import org .eclipse .core .resources .ResourcesPlugin ;
34+
35+ import org .eclipse .jface .dialogs .IDialogSettings ;
36+ import org .eclipse .jface .viewers .ISelectionProvider ;
37+
38+ import org .eclipse .jface .text .Document ;
39+ import org .eclipse .jface .text .TextSelection ;
40+
41+ import org .eclipse .ui .IEditorPart ;
42+ import org .eclipse .ui .IWorkbench ;
43+ import org .eclipse .ui .IWorkbenchPage ;
44+ import org .eclipse .ui .IWorkbenchPartSite ;
45+ import org .eclipse .ui .PartInitException ;
46+ import org .eclipse .ui .PlatformUI ;
47+ import org .eclipse .ui .ide .IDE ;
48+ import org .eclipse .ui .internal .findandreplace .HistoryStore ;
49+
50+ import org .eclipse .ui .texteditor .AbstractTextEditor ;
51+ import org .eclipse .ui .texteditor .FindNextAction ;
52+ import org .eclipse .ui .texteditor .FindReplaceAction ;
53+
54+ public class FindNextActionTest {
55+ private static final String TEST_PROJECT_NAME = "TestProject" ;
56+
57+ private static final String BUNDLE_FOR_CONSTRUCTED_KEYS_NAME = "org.eclipse.ui.texteditor.ConstructedEditorMessages" ;//$NON-NLS-1$
58+
59+ private static ResourceBundle bundleForConstructedKeys = ResourceBundle .getBundle (BUNDLE_FOR_CONSTRUCTED_KEYS_NAME );
60+
61+ private AbstractTextEditor editor ;
62+
63+ private IProject project ;
64+
65+ private FindNextAction action ;
66+
67+ private static enum Direction {
68+ FORWARD , BACKWARD
69+ }
70+
71+ @ Before
72+ public void createTestProject () throws CoreException {
73+ project = ResourcesPlugin .getWorkspace ().getRoot ().getProject (TEST_PROJECT_NAME );
74+ project .create (null );
75+ project .open (null );
76+ }
77+
78+ public void openEditorAndFindNextAction (String content , Direction direction ) throws CoreException {
79+ IFile file = createTestFile (content );
80+ editor = openEditor (file );
81+ action = new FindNextAction (bundleForConstructedKeys , "findNext" , editor , direction == Direction .FORWARD );
82+ }
83+
84+ private IFile createTestFile (String content ) throws CoreException {
85+ IFile file = project .getFile ("file.txt" );
86+ file .create (content .getBytes (), IResource .FORCE , null );
87+ file .setCharset (null , null );
88+ return file ;
89+ }
90+
91+ private static AbstractTextEditor openEditor (IFile file ) throws PartInitException {
92+ IWorkbench workbench = PlatformUI .getWorkbench ();
93+ IWorkbenchPage page = workbench .getActiveWorkbenchWindow ().getActivePage ();
94+ IEditorPart editorPart = IDE .openEditor (page , file );
95+ assertThat (editorPart , Matchers .instanceOf (AbstractTextEditor .class ));
96+ return (AbstractTextEditor ) editorPart ;
97+ }
98+
99+ @ After
100+ public void tearDown () throws Exception {
101+ resetInitialSearchSettings ();
102+ closeEditor (editor );
103+ editor = null ;
104+ project .delete (true , null );
105+ project = null ;
106+ TestUtil .cleanUp ();
107+ }
108+
109+ private void resetInitialSearchSettings () {
110+ IDialogSettings settings = getActionSettings ();
111+ settings .put ("isRegEx" , false );
112+ settings .put ("casesensitive" , false );
113+ settings .put ("wrap" , true );
114+ settings .put ("wholeword" , false );
115+ }
116+
117+ private static void closeEditor (IEditorPart editor ) {
118+ IWorkbenchPartSite site ;
119+ IWorkbenchPage page ;
120+ if (editor != null && (site = editor .getSite ()) != null && (page = site .getPage ()) != null ) {
121+ page .closeEditor (editor , false );
122+ }
123+ }
124+
125+ private void setEditorSelection (int offset , int length ) {
126+ Document document = (Document ) editor .getDocumentProvider ().getDocument (editor .getEditorInput ());
127+ TextSelection selection = new TextSelection (document , offset , length );
128+ ISelectionProvider selectionProvider = editor .getSelectionProvider ();
129+ selectionProvider .setSelection (selection );
130+ }
131+
132+ private void assertSelectionIs (int offset , int length ) {
133+ assertEquals (offset , getEditorSelection ().getRegions ()[0 ].getOffset ());
134+ assertEquals (length , getEditorSelection ().getRegions ()[0 ].getLength ());
135+ }
136+
137+ private TextSelection getEditorSelection () {
138+ ISelectionProvider selectionProvider = editor .getSelectionProvider ();
139+ if (selectionProvider .getSelection () instanceof TextSelection ) {
140+ return (TextSelection ) selectionProvider .getSelection ();
141+ }
142+ return null ;
143+ }
144+
145+ private IDialogSettings getActionSettings () {
146+ IDialogSettings settings = PlatformUI .getDialogSettingsProvider (FrameworkUtil .getBundle (FindNextAction .class ))
147+ .getDialogSettings ();
148+ IDialogSettings fDialogSettings = settings .getSection (FindReplaceAction .class .getClass ().getName ());
149+ if (fDialogSettings == null )
150+ fDialogSettings = settings .addNewSection (FindReplaceAction .class .getClass ().getName ());
151+ return fDialogSettings ;
152+ }
153+
154+ @ Test
155+ public void testFindNextForward () throws CoreException {
156+ openEditorAndFindNextAction ("testtesttest" , Direction .FORWARD );
157+ setEditorSelection (0 , 4 );
158+ action .run ();
159+ assertSelectionIs (4 , 4 );
160+ action .run ();
161+ assertSelectionIs (8 , 4 );
162+ action .run ();
163+ assertSelectionIs (0 , 4 );
164+ }
165+
166+ @ Test
167+ public void testFindNextBackwards () throws CoreException {
168+ openEditorAndFindNextAction ("testtesttest" , Direction .BACKWARD );
169+ setEditorSelection (4 , 4 );
170+ action .run ();
171+ assertSelectionIs (0 , 4 );
172+ action .run ();
173+ assertSelectionIs (8 , 4 );
174+ }
175+
176+ @ Test
177+ public void testFindNextFromHistory () throws CoreException {
178+ openEditorAndFindNextAction ("word-abcd-text" , Direction .FORWARD );
179+ IDialogSettings settings = getActionSettings ();
180+ HistoryStore historyStore = new HistoryStore (settings , "findhistory" , 15 );
181+ historyStore .add ("abcd" );
182+ setEditorSelection (0 , 0 );
183+ action .run ();
184+ assertSelectionIs (5 , 4 );
185+ setEditorSelection (3 , 0 );
186+ action .run ();
187+ assertSelectionIs (5 , 4 );
188+ }
189+
190+ @ Test
191+ public void testFindNextStoresCorrectHistory () throws CoreException {
192+ openEditorAndFindNextAction ("history" , Direction .FORWARD );
193+ setEditorSelection (0 , "history" .length ());
194+ action .run ();
195+ IDialogSettings settings = getActionSettings ();
196+ HistoryStore historyStore = new HistoryStore (settings , "findhistory" , 15 );
197+ assertThat (historyStore .get (0 ), is ("history" ));
198+ }
199+
200+ @ Test
201+ public void testFindNextWithRegExEscapedCorrectly () throws CoreException {
202+ openEditorAndFindNextAction ("wo+rd-woord" , Direction .FORWARD );
203+ IDialogSettings settings = getActionSettings ();
204+ setEditorSelection (0 , 5 );
205+ settings .put ("isRegEx" , true );
206+ action .run ();
207+ assertSelectionIs (0 , 5 );
208+ }
209+
210+ @ Test
211+ public void testCaseSensitiveFindNext () throws CoreException {
212+ openEditorAndFindNextAction ("wordWORD" , Direction .FORWARD );
213+ IDialogSettings settings = getActionSettings ();
214+ settings .put ("casesensitive" , true );
215+ setEditorSelection (0 , 4 );
216+ action .run ();
217+ assertSelectionIs (0 , 4 );
218+ }
219+
220+ @ Test
221+ public void testFindNextMultilineSelection () throws CoreException {
222+ openEditorAndFindNextAction ("line\n \r next\n \r next\r \n line" , Direction .FORWARD );
223+ // we expect the search string to only contain the first line
224+ setEditorSelection (0 , 10 );
225+ action .run ();
226+ assertSelectionIs (18 , 4 );
227+ }
228+
229+ @ Test
230+ public void testFindNextNoWrap () throws CoreException {
231+ openEditorAndFindNextAction ("wordword" , Direction .FORWARD );
232+ IDialogSettings settings = getActionSettings ();
233+ settings .put ("wrap" , false );
234+ setEditorSelection (0 , 4 );
235+ action .run ();
236+ assertSelectionIs (4 , 4 );
237+ action .run ();
238+ assertSelectionIs (4 , 4 );
239+ }
240+
241+ @ Test
242+ public void testFindWholeWords () throws CoreException {
243+ openEditorAndFindNextAction ("word longerword word" , Direction .FORWARD );
244+ IDialogSettings settings = getActionSettings ();
245+ settings .put ("wholeword" , true );
246+ setEditorSelection (0 , 4 );
247+ action .run ();
248+ assertSelectionIs (16 , 4 );
249+ }
250+
251+ @ Test
252+ public void testFindWholeWordsIsNotWord () throws CoreException {
253+ openEditorAndFindNextAction ("w ord longerw ordinner w ord" , Direction .FORWARD );
254+ IDialogSettings settings = getActionSettings ();
255+ settings .put ("wholeword" , true );
256+ setEditorSelection (0 , 5 );
257+ action .run ();
258+ assertSelectionIs (12 , 5 );
259+ action .run ();
260+ assertSelectionIs (23 , 5 );
261+ }
262+
263+ }
0 commit comments