Skip to content

Commit

Permalink
Move activation logic for SearchOptions.WHOLE_WORDS to FindReplaceLogic
Browse files Browse the repository at this point in the history
when "whole words" is selected but a find-string was entered that is not
a whole word, the dialog/overlay will disable the option for "whole
words". However, the dialog/overlay will keep the selection of the
button in it's internal state. By passing the findString to this method,
we can make sure that we don't try to perform a whole-words search for a
string that isn't a whole word.

See eclipse-platform#1192 (comment)

Extracted from
eclipse-platform#1192
  • Loading branch information
Maximilian Wittmer authored and HeikoKlare committed Apr 10, 2024
1 parent 81709ca commit 781d89e
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,19 @@ private void resetStatus() {
status = null;
}

@Override
public boolean isWholeWordSearchAvailable(String findString) {
return !isRegExSearchAvailableAndActive() && isWord(findString);
}

/**
* Returns <code>true</code> if searching should be restricted to entire words,
* <code>false</code> if not. This is the case if the respective checkbox is
* turned on, regex is off, and the checkbox is enabled, i.e. the current find
* string is an entire word.
* Tests whether each character in the given string is a letter.
*
* @return <code>true</code> if the search is restricted to whole words
* @param str the string to check
* @return <code>true</code> if the given string is a word
*/
private boolean isWholeWordSearchAvailableAndActive() {
return isActive(SearchOptions.WHOLE_WORD) && !isRegExSearchAvailableAndActive();
private static boolean isWord(String str) {
return str != null && !str.isEmpty() && str.chars().allMatch(Character::isJavaIdentifierPart);
}

@Override
Expand Down Expand Up @@ -495,13 +498,18 @@ private int findIndex(String findString, int startPosition) {

@Override
public int findAndSelect(int offset, String findString) {
if (target instanceof IFindReplaceTargetExtension3)
return ((IFindReplaceTargetExtension3) target).findAndSelect(offset, findString,
isActive(SearchOptions.FORWARD),
isActive(SearchOptions.CASE_SENSITIVE), isWholeWordSearchAvailableAndActive(), isActive(SearchOptions.REGEX));
return target.findAndSelect(offset, findString, isActive(SearchOptions.FORWARD),
isActive(SearchOptions.CASE_SENSITIVE),
isWholeWordSearchAvailableAndActive());
boolean wholeWordSearch = isActive(SearchOptions.WHOLE_WORD) && isWholeWordSearchAvailable(findString);
boolean forwardSearch = isActive(SearchOptions.FORWARD);
boolean caseSensitiveSearch = isActive(SearchOptions.CASE_SENSITIVE);
boolean regexSearch = isActive(SearchOptions.REGEX);

if (target instanceof IFindReplaceTargetExtension3 regexSupportingTarget) {
return (regexSupportingTarget).findAndSelect(offset, findString,
forwardSearch, caseSensitiveSearch,
wholeWordSearch, regexSearch);
}
return target.findAndSelect(offset, findString, forwardSearch,
caseSensitiveSearch, wholeWordSearch);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,14 @@ public interface IFindReplaceLogic {
*/
public IFindReplaceTarget getTarget();

/**
* Returns <code>true</code> if searching can be restricted to entire words,
* <code>false</code> if not. Searching for whole words requires the given find
* string to be an entire word and the regex search option to be disabled.
*
* @param findString the string that is currently being searched for.
* @return <code>true</code> if the search can be restricted to whole words
*/
public boolean isWholeWordSearchAvailable(String findString);

}
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ public void widgetSelected(SelectionEvent e) {
}
});
storeButtonWithMnemonicInMap(fIsRegExCheckBox);
fWholeWordCheckBox.setEnabled(!findReplaceLogic.isRegExSearchAvailableAndActive());
fWholeWordCheckBox.setEnabled(findReplaceLogic.isWholeWordSearchAvailable(getFindString()));
fWholeWordCheckBox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Expand Down Expand Up @@ -1065,7 +1065,7 @@ private void updateButtonState(boolean disableReplace) {
boolean isSelectionGoodForReplace = selectionString != "" //$NON-NLS-1$
|| !isRegExSearchAvailableAndActive;

fWholeWordCheckBox.setEnabled(isWord(str) && !isRegExSearchAvailableAndActive);
fWholeWordCheckBox.setEnabled(findReplaceLogic.isWholeWordSearchAvailable(getFindString()));
fFindNextButton.setEnabled(enable && isFindStringSet);
fSelectAllButton.setEnabled(enable && isFindStringSet && (target instanceof IFindReplaceTargetExtension4));
fReplaceSelectionButton.setEnabled(
Expand All @@ -1076,23 +1076,6 @@ private void updateButtonState(boolean disableReplace) {
}
}

/**
* Tests whether each character in the given string is a letter.
*
* @param str the string to check
* @return <code>true</code> if the given string is a word
* @since 3.0
*/
private boolean isWord(String str) {
if (str == null || str.isEmpty())
return false;

for (int i = 0; i < str.length(); i++) {
if (!Character.isJavaIdentifierPart(str.charAt(i)))
return false;
}
return true;
}

/**
* Updates the given combo with the given content.
Expand Down Expand Up @@ -1178,7 +1161,7 @@ public void updateTarget(IFindReplaceTarget target, boolean isTargetEditable, bo
}

if (okToUse(fWholeWordCheckBox)) {
fWholeWordCheckBox.setEnabled(!findReplaceLogic.isRegExSearchAvailableAndActive());
fWholeWordCheckBox.setEnabled(findReplaceLogic.isWholeWordSearchAvailable(getFindString()));
}

if (okToUse(fIncrementalCheckBox)) {
Expand Down Expand Up @@ -1280,8 +1263,7 @@ private void setupFindReplaceLogic() {
activateInFindReplaceLogicIf(SearchOptions.FORWARD, fForwardRadioButton.getSelection());
activateInFindReplaceLogicIf(SearchOptions.CASE_SENSITIVE, fCaseCheckBox.getSelection());
activateInFindReplaceLogicIf(SearchOptions.REGEX, fIsRegExCheckBox.getSelection());
activateInFindReplaceLogicIf(SearchOptions.WHOLE_WORD,
fWholeWordCheckBox.getEnabled() && fWholeWordCheckBox.getSelection());
activateInFindReplaceLogicIf(SearchOptions.WHOLE_WORD, fWholeWordCheckBox.getSelection());
activateInFindReplaceLogicIf(SearchOptions.INCREMENTAL,
fIncrementalCheckBox.getEnabled() && fIncrementalCheckBox.getSelection());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,28 @@ public void testSelectInSearchScope() {
assertThat(textViewer.getTextWidget().getText(), is("lie1\nine2\nine3"));
}

@Test
public void testWholeWordSearchAvailable() {
TextViewer textViewer= setupTextViewer("line1\nline2\nline3");
IFindReplaceLogic findReplaceLogic= setupFindReplaceLogicObject(textViewer);

assertThat(findReplaceLogic.isWholeWordSearchAvailable("oneword"), is(true));
assertThat(findReplaceLogic.isWholeWordSearchAvailable("stilläoneäword"), is(true));
assertThat(findReplaceLogic.isWholeWordSearchAvailable("two.words"), is(false));
assertThat(findReplaceLogic.isWholeWordSearchAvailable("two words"), is(false));
assertThat(findReplaceLogic.isWholeWordSearchAvailable("oneword"), is(true));
assertThat(findReplaceLogic.isWholeWordSearchAvailable("twöwords"), is(true));

findReplaceLogic.activate(SearchOptions.REGEX);

assertThat(findReplaceLogic.isWholeWordSearchAvailable("oneword"), is(false));
assertThat(findReplaceLogic.isWholeWordSearchAvailable("stilläoneöword"), is(false));
assertThat(findReplaceLogic.isWholeWordSearchAvailable("two.words"), is(false));
assertThat(findReplaceLogic.isWholeWordSearchAvailable("two words"), is(false));

assertThat(findReplaceLogic.isWholeWordSearchAvailable(""), is(false));
}

private void expectStatusEmpty(IFindReplaceLogic findReplaceLogic) {
assertThat(findReplaceLogic.getStatus(), instanceOf(NoStatus.class));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,28 @@ public void testReplaceAndFindAfterInitializingFindWithSelectedString() {
assertEquals(4, (target.getSelection()).y);
}

@Test
public void testActivateWholeWordsAndSearchForTwoWords() {
openTextViewer("text text text");
openFindReplaceDialogForTextViewer();

dialog.wholeWordCheckBox.setSelection(true);

dialog.findCombo.setText("text text");
assertTrue(dialog.wholeWordCheckBox.getSelection());
assertFalse(dialog.wholeWordCheckBox.getEnabled());

dialog.findCombo.setText("text");
assertTrue(dialog.wholeWordCheckBox.getSelection());
assertTrue(dialog.wholeWordCheckBox.getEnabled());

dialog.regExCheckBox.setSelection(true);
dialog.regExCheckBox.notifyListeners(SWT.Selection, null);
runEventQueue();
assertTrue(dialog.wholeWordCheckBox.getSelection());
assertFalse(dialog.wholeWordCheckBox.getEnabled());
}

private static void select(Button button) {
button.setSelection(true);
button.notifyListeners(SWT.Selection, null);
Expand Down

0 comments on commit 781d89e

Please sign in to comment.