diff --git a/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF b/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF index 5196da7553e..29a2defc9e4 100644 --- a/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jface.text -Bundle-Version: 3.25.200.qualifier +Bundle-Version: 3.25.300.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/html/HTML2TextReader.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/html/HTML2TextReader.java index 8f8aa4ba64f..1ad32765258 100644 --- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/html/HTML2TextReader.java +++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/html/HTML2TextReader.java @@ -25,6 +25,8 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; +import org.eclipse.text.readers.SubstitutionReader; + import org.eclipse.jface.text.TextPresentation; @@ -34,7 +36,7 @@ *

* Moved into this package from org.eclipse.jface.internal.text.revisions.

*/ -public class HTML2TextReader extends SubstitutionTextReader { +public class HTML2TextReader extends SubstitutionReader { private static final String EMPTY_STRING= ""; //$NON-NLS-1$ private static final Map fgEntityLookup; diff --git a/bundles/org.eclipse.text.quicksearch/META-INF/MANIFEST.MF b/bundles/org.eclipse.text.quicksearch/META-INF/MANIFEST.MF index a720ebaeb85..d656db96eda 100644 --- a/bundles/org.eclipse.text.quicksearch/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.text.quicksearch/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.text.quicksearch;singleton:=true -Bundle-Version: 1.2.400.qualifier +Bundle-Version: 1.2.500.qualifier Bundle-Activator: org.eclipse.text.quicksearch.internal.ui.QuickSearchActivator Require-Bundle: org.eclipse.ui;bundle-version="[3.113.0,4.0.0)", org.eclipse.core.resources;bundle-version="[3.13.0,4.0.0)", diff --git a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/QuickTextQuery.java b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/QuickTextQuery.java index 608143eef40..552912ab95c 100644 --- a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/QuickTextQuery.java +++ b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/QuickTextQuery.java @@ -48,7 +48,7 @@ public int getOffset() { private boolean caseInsensitive; private String orgPattern; //Original pattern case preserved even if search is case insensitive. - private Pattern pattern; + final Pattern pattern; /** * A query that matches anything. @@ -60,15 +60,11 @@ public QuickTextQuery() { public QuickTextQuery(String substring, boolean caseInsensitive) { this.orgPattern = substring; this.caseInsensitive = caseInsensitive; - createMatcher(substring, caseInsensitive); + String regex = createRegEx(substring); + pattern = Pattern.compile(regex, caseInsensitive ? Pattern.CASE_INSENSITIVE : 0); } - /** - * Compile a pattern string into an RegExp and create a Matcher for that - * regexp. This is so we can 'compile' the pattern once and then keep reusing - * the matcher or compiled pattern. - */ - private void createMatcher(String patString, boolean caseSensitive) { + private String createRegEx(String patString) { StringBuilder segment = new StringBuilder(); //Accumulates text that needs to be 'quoted' StringBuilder regexp = new StringBuilder(); //Accumulates 'compiled' pattern int pos = 0, len = patString.length(); @@ -101,8 +97,7 @@ private void createMatcher(String patString, boolean caseSensitive) { //Don't forget to process that last segment. appendSegment(segment, regexp); - this.pattern = Pattern.compile(regexp.toString(), caseSensitive? Pattern.CASE_INSENSITIVE : 0); -// this.matcher = pattern.matcher(""); + return regexp.toString(); } private void appendSegment(StringBuilder segment, StringBuilder regexp) { @@ -157,25 +152,6 @@ private String normalize(String pat, boolean caseSensitive) { return pat; } - /** - * @return whether the LineItem text contains the search pattern. - */ - public boolean matchItem(LineItem item) { - return matchItem(item.getText()); - } - - /** - * Same as matchItem except only takes the text of the item. This can - * be useful for efficient processing. In particular to avoid creating - * LineItem instances for non-matching lines. - */ - public boolean matchItem(String item) { - //Alternate implementation. This is thread safe without synchronized, - // but it creates some garbage. - Matcher matcher = pattern.matcher(item); //Creating garbage here - return matcher.find(); - } - /** * A trivial query is one that either * - matches anything diff --git a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/QuickTextSearcher.java b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/QuickTextSearcher.java index 905a6a2e833..31a1431c75f 100644 --- a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/QuickTextSearcher.java +++ b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/QuickTextSearcher.java @@ -13,12 +13,20 @@ package org.eclipse.text.quicksearch.internal.core; import java.io.InputStreamReader; -import java.util.HashSet; +import java.io.Reader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; import java.util.Iterator; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; @@ -32,6 +40,7 @@ import org.eclipse.text.quicksearch.internal.util.LineReader; public class QuickTextSearcher { + private static int MAX_BUFFER_LENGTH = 999_999; // read max 1MB bytes => max 2MB chars. private final QuickTextSearchRequestor requestor; private QuickTextQuery query; @@ -39,14 +48,14 @@ public class QuickTextSearcher { * Keeps track of currently found matches. Items are added as they are found and may also * be removed when the query changed and they become invalid. */ - private Set matches = new HashSet<>(2000); + private final Set matches = ConcurrentHashMap.newKeySet(2000); /** * Scheduling rule used by Jobs that work on the matches collection. */ private ISchedulingRule matchesRule = new LightSchedulingRule("QuickSearchMatchesRule"); //$NON-NLS-1$ - private SearchInFilesWalker walker = null; + private final SearchInFilesWalker walker; private IncrementalUpdateJob incrementalUpdate; /** @@ -75,7 +84,8 @@ public class QuickTextSearcher { * While searching in a file, this field will be set. This can be used to show the name * of the 'current file' in the progress area of the quicksearch dialog. */ - private IFile currentFile = null; + private volatile IFile currentFile = null; + public volatile int searchTookMs; /** * Flag to disable incremental filtering logic based on incremental @@ -124,35 +134,62 @@ private SearchInFilesWalker createWalker(PriorityFunction priorities) { private final class SearchInFilesWalker extends ResourceWalker { - @Override - protected void visit(IFile f, IProgressMonitor mon) { - if (checkCanceled(mon)) { - return; + public IStatus run(IProgressMonitor monitor) { + searchTookMs = 0; + long n0 = System.nanoTime(); + try { + return super.run(monitor); + } finally { + currentFile = null; + long n1 = System.nanoTime(); + if (matches.isEmpty()) { + searchTookMs = (int) ((n1 - n0) / 1_000_000); + } } + } + @Override + protected boolean searchIn(IFile f, BooleanSupplier canceled) { currentFile = f; - try (LineReader lr = new LineReader(new InputStreamReader(f.getContents(true), f.getCharset()), MAX_LINE_LEN)) { - String line = null; + return search(f, canceled, MAX_LINE_LEN, query.pattern, QuickTextSearcher.this::add); + } + + private static boolean search(IFile f, BooleanSupplier canceled, + int maxLineLength, Pattern pattern, Consumer add) { + if (canceled.getAsBoolean()) { + return false; + } + try (LineReader lr = new LineReader(getReader(f), + maxLineLength)) { + String line; int lineIndex = 1; while ((line = lr.readLine()) != null) { int offset = lr.getLastLineOffset(); - if (checkCanceled(mon)) { - return; + if (canceled.getAsBoolean()) { + return false; } - boolean found = query.matchItem(line); - if (found) { + Matcher matcher = pattern.matcher(line); + if (matcher.find()) { LineItem lineItem = new LineItem(f, line, lineIndex, offset); - add(lineItem); + add.accept(lineItem); } lineIndex++; } } catch (Exception e) { // ignored - } finally { - currentFile = null; + } + return true; + } + + private static Reader getReader(IFile f) throws UnsupportedEncodingException, CoreException { + String shortString = toShortString(f); + if (shortString != null) { + return new StringReader(shortString); + } else { + return new InputStreamReader(f.getContents(true), f.getCharset()); } } @@ -164,18 +201,27 @@ public void resume() { } } - private boolean checkCanceled(IProgressMonitor mon) { - return mon.isCanceled(); - } - - public void requestMoreResults() { - int currentSize = matches.size(); - maxResults = Math.max(maxResults, currentSize + currentSize/10); - resume(); + } + /** + * Try to get a content as String. Avoids Streaming. + */ + private static String toShortString(IFile file) { + /** + * Just any number such that the most source files will fit in. And not too + * big to avoid out of memory. + **/ + try { + byte[] content = file.readNBytes(MAX_BUFFER_LENGTH); + int length = content.length; + if (length >= MAX_BUFFER_LENGTH) { + return null; + } + String charset = file.getCharset(); + return new String(content, charset); + } catch (Exception e) { + return null; } - } - /** * This job updates already found matches when the query is changed. * Both the walker job and this job share the same scheduling rule so @@ -203,9 +249,11 @@ protected IStatus run(IProgressMonitor monitor) { } else { query = nq; forceRefresh = false; - performRestart(); + if (!monitor.isCanceled()) { // avoid restart if dialog got closed + performRestart(); + } } - return monitor.isCanceled()?Status.CANCEL_STATUS:Status.OK_STATUS; + return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; } private void performIncrementalUpdate(IProgressMonitor mon) { @@ -213,7 +261,8 @@ private void performIncrementalUpdate(IProgressMonitor mon) { while (items.hasNext() && !mon.isCanceled()) { LineItem item = items.next(); - if (query.matchItem(item)) { + Matcher matcher = query.pattern.matcher(item.getText()); + if (matcher.find()) { //Match still valid but may need updating highlighted text in the UI: requestor.update(item); } else { @@ -228,31 +277,26 @@ private void performIncrementalUpdate(IProgressMonitor mon) { } private void performRestart() { - //walker may be null if dialog got closed already before we managed to - // 'performRestart'. - if (walker!=null) { - //since we are inside Job here that uses same scheduling rule as walker, we - //know walker is not currently executing. so walker cancel should be instantenous - matches.clear(); - requestor.clear(); - walker.cancel(); - if (!query.isTrivial()) { - walker.init(); //Reinitialize the walker work queue to its starting state - walker.resume(); //Allow walker to resume when we release the scheduling rule. - } else { - walker.stop(); - } + //since we are inside Job here that uses same scheduling rule as walker, we + //know walker is not currently executing. so walker cancel should be instantenous + matches.clear(); + requestor.clear(); + walker.cancel(); + if (!query.isTrivial()) { + walker.init(); //Reinitialize the walker work queue to its starting state + walker.resume(); //Allow walker to resume when we release the scheduling rule. + } else { + walker.stop(); } } } private void add(LineItem line) { - if (matches.add(line)) { + if (!isActive()) { + walker.suspend(); + } else if (matches.add(line)) { requestor.add(line); - if (!isActive()) { - walker.suspend(); - } } } @@ -261,7 +305,7 @@ public void setQuery(QuickTextQuery newQuery, boolean force) { return; } this.newQuery = newQuery; - this.forceRefresh = true; + this.forceRefresh = force; scheduleIncrementalUpdate(); } @@ -304,19 +348,13 @@ public boolean isDone() { //Walker can be null if job was canceled because dialog closed. But stuff like //the job that shows 'Searching ...' doesn't instantly stop and may still //be asking the incremental update job whether its done. - return /*(incrementalUpdate != null && incrementalUpdate.getState() != Job.NONE) ||*/ (walker!=null && walker.isDone()); - } - - public void requestMoreResults() { - if (walker!=null && !walker.isDone()) { - walker.requestMoreResults(); - } + return /*(incrementalUpdate != null && incrementalUpdate.getState() != Job.NONE) ||*/ walker.isDone(); } public void cancel() { - if (walker!=null) { - walker.cancel(); - walker = null; + walker.cancel(); + if (incrementalUpdate instanceof IncrementalUpdateJob update) { + update.cancel(); } } diff --git a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/ResourceWalker.java b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/ResourceWalker.java index 6cc392ecd86..1f46bf2f9ac 100644 --- a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/ResourceWalker.java +++ b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/ResourceWalker.java @@ -12,7 +12,14 @@ *******************************************************************************/ package org.eclipse.text.quicksearch.internal.core; +import java.util.Collection; import java.util.PriorityQueue; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; @@ -39,15 +46,7 @@ */ public abstract class ResourceWalker extends Job { - private static class QItem implements Comparable { - public final double priority; - public final IResource resource; - - public QItem(double p, IResource r) { - this.priority = p; - this.resource = r; - } - + private static record QItem(double priority, IResource resource) implements Comparable { @Override public int compareTo(QItem other) { return Double.compare(other.priority, this.priority); @@ -60,27 +59,47 @@ public ResourceWalker() { } protected void init() { - queue = new PriorityQueue<>(); - queue.add(new QItem(0, ResourcesPlugin.getWorkspace().getRoot())); + filesToSearch.clear(); + addRecursive(filesToSearch, new QItem(0, ResourcesPlugin.getWorkspace().getRoot())); + } + + private void addRecursive(Collection queue, QItem item) { + IResource r = item.resource; + if (r instanceof IFile) { + queue.add(item); + } else if (r instanceof IContainer f) { + if (f.isAccessible()) { + try { + for (IResource child : f.members()) { + double p = priority(child); + if (p != PriorityFunction.PRIORITY_IGNORE) { + addRecursive(queue, new QItem(p, child)); + } + } + } catch (CoreException e) { + QuickSearchActivator.log(e); + } + } + } } /** - * Queue of work to do. When all work is done this will be set to null. So it + * Work to do. When all work is done this is empty. So it * can also be used to determine 'done' status. */ - private PriorityQueue queue = null; + private final Set filesToSearch = ConcurrentHashMap.newKeySet(); /** * Setting this to true will cause the ResourceWalker to stop walking. If the walker is running * as a scheduled job, then this Job will terminate. However it is possible to 'resume' the * later since pending list of workitems will be retained. */ - private boolean suspend = false; + private volatile boolean suspend = false; private PriorityFunction prioritFun = new DefaultPriorityFunction(); public boolean isDone() { - return queue==null; + return filesToSearch.isEmpty(); } /** @@ -95,7 +114,7 @@ public void suspend() { * all pending workitems. The walker cannot be resumed and must be reinitialized. */ public void stop() { - this.queue = null; + this.filesToSearch.clear(); this.suspend = false; } @@ -119,32 +138,42 @@ public void resume() { @Override public IStatus run(IProgressMonitor monitor) { - //TODO: progress reporting? - while (!suspend && queue!=null) { - if (monitor.isCanceled()) { - queue = null; - } else { - IResource r = getWork(); - if (r!=null) { - if (r instanceof IFile) { + int workers = Math.max(1, Runtime.getRuntime().availableProcessors() - 1); + ExecutorService executorService = Executors.newFixedThreadPool(workers); + // copy the filesToSearch, to only remove a file after search completed + PriorityQueue queue = new PriorityQueue<>(); + queue.addAll(filesToSearch); + for (int worker = 0; worker < workers; worker++) { + executorService.submit(() -> { + QItem item; + while ((item = queue.poll()) != null) { + if (monitor.isCanceled() || suspend) { + break; + } else { + IResource r = item.resource; IFile f = (IFile) r; - visit(f, monitor); - } else if (r instanceof IContainer) { - IContainer f = (IContainer) r; - if (f.isAccessible()) { - try { - for (IResource child : f.members()) { - enqueue(child); - } - } catch (CoreException e) { - QuickSearchActivator.log(e); - } + boolean searched = searchIn(f, () -> monitor.isCanceled() || suspend); + if (searched) { + filesToSearch.remove(item); } } - } else { - queue = null; + } + }); + } + try { + while (!executorService.awaitTermination(1, TimeUnit.MILLISECONDS)) { + executorService.shutdown(); + if (monitor.isCanceled() || suspend) { + queue.clear(); + executorService.shutdownNow(); } } + } catch (InterruptedException e) { + // ignore + } + // on suspend keep unsearched files for later + if (!suspend) { + filesToSearch.clear(); } if (monitor.isCanceled()) { return Status.CANCEL_STATUS; @@ -153,21 +182,7 @@ public IStatus run(IProgressMonitor monitor) { } } - /** - * Add a resource to the work queue taking account the priority of the resource. - */ - private void enqueue(IResource child) { - PriorityQueue q = queue; - if (q!=null) { - double p = priority(child); - if (p==PriorityFunction.PRIORITY_IGNORE) { - return; - } - q.add(new QItem(p, child)); - } - } - - protected abstract void visit(IFile r, IProgressMonitor m); + protected abstract boolean searchIn(IFile f, BooleanSupplier canceled); /** * Assigns a priority to a given resource. This priority will affect the order in which @@ -197,14 +212,4 @@ public void setPriorityFun(PriorityFunction f) { Assert.isNotNull(f, "PriorityFunction should never be null"); //$NON-NLS-1$ this.prioritFun = f; } - - private IResource getWork() { - PriorityQueue q = queue; - if (q!=null && !q.isEmpty()) { - return q.remove().resource; - } - return null; - } - - } diff --git a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/priority/PriorityFunction.java b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/priority/PriorityFunction.java index 8dc5b9001aa..a01e0396f66 100644 --- a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/priority/PriorityFunction.java +++ b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/core/priority/PriorityFunction.java @@ -20,15 +20,6 @@ */ public abstract class PriorityFunction { - /** - * The highest priority. Any elements in the queue with this priority will be visited before - * any others in the queue. Be warned that assigning this priority to a deeply nested - * element in the tree alone doesn't guarantee it will be visited early on because in - * order to reach the element the parents have to be visited first. If the parent - * has a low priority... - */ - public static final double PRIORITY_HIGHEST = Double.POSITIVE_INFINITY; - /** * Priority indicating something that is moderately more interesting than the default. * So it should be processed before default stuff but not before "VISIT_FIRST" priority. diff --git a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/Messages.java b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/Messages.java index b1dc47b34f9..8795635a9e8 100644 --- a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/Messages.java +++ b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/Messages.java @@ -42,6 +42,7 @@ public class Messages extends NLS { public static String QuickSearchDialog_listLabel_limit_reached; public static String QuickSearchDialog_caseSensitive_label; public static String QuickSearchDialog_caseInsensitive_label; + public static String QuickSearchDialog_notFound; public static String QuickTextSearch_updateMatchesJob; public static String quickAccessMatch; diff --git a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/QuickSearchDialog.java b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/QuickSearchDialog.java index de32414572b..a2ddfbbef5b 100644 --- a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/QuickSearchDialog.java +++ b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/QuickSearchDialog.java @@ -112,7 +112,6 @@ import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.internal.IWorkbenchGraphicConstants; import org.eclipse.ui.internal.WorkbenchImages; -import org.eclipse.ui.internal.WorkbenchMessages; import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; import org.eclipse.ui.progress.UIJob; import org.osgi.framework.FrameworkUtil; @@ -180,13 +179,20 @@ protected String currentFileInfo(IFile currentFile, int animate) { @Override public IStatus runInUIThread(IProgressMonitor mon) { - if (!mon.isCanceled() && progressLabel!=null && !progressLabel.isDisposed()) { - if (searcher==null || !searcher.isActive()) { - progressLabel.setText(EMPTY_STRING); + if (!mon.isCanceled() && progressLabel != null && !progressLabel.isDisposed()) { + if (searcher == null || !searcher.isActive()) { + if (searcher != null && searcher.searchTookMs != 0) { + progressLabel.setText(Messages.QuickSearchDialog_notFound); + } else { + progressLabel.setText(EMPTY_STRING); + } } else { - progressLabel.setText(NLS.bind(Messages.QuickSearchDialog_searching, currentFileInfo(searcher.getCurrentFile(), animate))); - animate = (animate+1)%4; - this.schedule(333); + progressLabel.setText(NLS.bind(Messages.QuickSearchDialog_searching, + currentFileInfo(searcher.getCurrentFile(), animate))); + animate = (animate + 1) % 4; + } + if (searcher != null) { + this.schedule(100); } } return Status.OK_STATUS; @@ -605,7 +611,7 @@ private Label createLabels(Composite parent) { Label listLabel = new Label(labels, SWT.NONE); listLabel - .setText(WorkbenchMessages.FilteredItemsSelectionDialog_listLabel); + .setText(""); //$NON-NLS-1$ listLabel.addTraverseListener(e -> { if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) { @@ -644,7 +650,7 @@ public void mouseDown(MouseEvent e) { toolItem.setImage(WorkbenchImages .getImage(IWorkbenchGraphicConstants.IMG_LCL_VIEW_MENU)); toolItem - .setToolTipText(WorkbenchMessages.FilteredItemsSelectionDialog_menu); + .setToolTipText(""); //$NON-NLS-1$ toolItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { diff --git a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/messages.properties b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/messages.properties index aafb9970382..2c5e69c007d 100644 --- a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/messages.properties +++ b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/ui/messages.properties @@ -24,5 +24,6 @@ QuickSearchDialog_listLabel = &Matching items: {0} QuickSearchDialog_listLabel_limit_reached = &Matching items: {0} (limit reached) QuickSearchDialog_caseSensitive_label=Case SENSITIVE &Pattern (? = any character, * = any string) QuickSearchDialog_caseInsensitive_label=Case INSENSITIVE &Pattern (? = any character, * = any string) +QuickSearchDialog_notFound=NOT FOUND QuickTextSearch_updateMatchesJob=Update matches quickAccessMatch=`{0}` in {1} \ No newline at end of file diff --git a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/util/LineReader.java b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/util/LineReader.java index c72b00bde68..b74a174982e 100644 --- a/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/util/LineReader.java +++ b/bundles/org.eclipse.text.quicksearch/src/org/eclipse/text/quicksearch/internal/util/LineReader.java @@ -15,6 +15,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; +import java.io.StringReader; /** * Provides a helper to efficiently split a file into @@ -30,7 +31,7 @@ public class LineReader implements AutoCloseable{ private static final int EXPECTED_LINE_LENGTH = 160; public static final int DEFAULT_MAX_LINE_LENGTH = 1000; - private BufferedReader input; + private Reader input; //This simple implementation just wraps a BufferedReader and StringBuilder //to do the buffering and String building. @@ -43,21 +44,23 @@ public LineReader(Reader reader) { public LineReader(Reader reader, int maxLineLength) { input = buffered(reader); - MAX_LINE_LENGTH = maxLineLength; + this.maxLineLength = maxLineLength; } private StringBuilder line = new StringBuilder(EXPECTED_LINE_LENGTH); - private final int MAX_LINE_LENGTH; + private final int maxLineLength; private int lineOffset = -1; //Start pos of last line read. private int offset = 0; //position of next char in input. private int mark = 0; //mark offset in underlying stream - private BufferedReader buffered(Reader reader) { + private Reader buffered(Reader reader) { //If already buffered don't wrap it again. - if (reader instanceof BufferedReader) { - return (BufferedReader) reader; + if (reader instanceof StringReader sr) { + return sr; + } else if (reader instanceof BufferedReader br) { + return br; } else { return new BufferedReader(reader); } @@ -68,24 +71,19 @@ private BufferedReader buffered(Reader reader) { */ @Override public void close() { - BufferedReader toClose = null; - synchronized (input) { - if (input==null) { - return; - } - toClose = input; + Reader toClose = input; + try (toClose) { input = null; - } - try { - toClose.close(); - } catch (IOException e) { + } catch (IOException closeException) { //Ignore. + } finally { + input = null; } } public String readLine() throws IOException { lineOffset = offset; //remember start of line - int maxOffset = offset + MAX_LINE_LENGTH; + int maxOffset = offset + maxLineLength; //Read text until we see either a CR, CR LF or LF. int c = read(); if (c==-1) { @@ -96,7 +94,8 @@ public String readLine() throws IOException { line.append((char)c); c = read(); if (offset>maxOffset) { - throw new IOException("Very long lines of text. Minified file?"); //$NON-NLS-1$ + // Very long lines of text. Minified file? + return null; } } //Last char read was some kind of line terminator. But only read first char of it. diff --git a/bundles/org.eclipse.text/META-INF/MANIFEST.MF b/bundles/org.eclipse.text/META-INF/MANIFEST.MF index 923f0a1dd86..82a999a525b 100644 --- a/bundles/org.eclipse.text/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.text/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.text -Bundle-Version: 3.14.100.qualifier +Bundle-Version: 3.14.200.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: diff --git a/bundles/org.eclipse.ui.browser/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.browser/META-INF/MANIFEST.MF index 4b6bc29fea6..8049331a308 100644 --- a/bundles/org.eclipse.ui.browser/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.ui.browser/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Plugin.name Bundle-SymbolicName: org.eclipse.ui.browser; singleton:=true -Bundle-Version: 3.8.300.qualifier +Bundle-Version: 3.8.400.qualifier Bundle-Activator: org.eclipse.ui.internal.browser.WebBrowserUIPlugin Bundle-Vendor: %Plugin.providerName Bundle-Localization: plugin diff --git a/bundles/org.eclipse.ui.editors/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.editors/META-INF/MANIFEST.MF index 2d1881470e1..e3cf47afb07 100644 --- a/bundles/org.eclipse.ui.editors/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.ui.editors/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.ui.editors; singleton:=true -Bundle-Version: 3.18.0.qualifier +Bundle-Version: 3.18.100.qualifier Bundle-Activator: org.eclipse.ui.internal.editors.text.EditorsPlugin Bundle-ActivationPolicy: lazy Bundle-Vendor: %providerName diff --git a/bundles/org.eclipse.ui.editors/plugin.properties b/bundles/org.eclipse.ui.editors/plugin.properties index c1eccc9c98e..5a246191f2b 100644 --- a/bundles/org.eclipse.ui.editors/plugin.properties +++ b/bundles/org.eclipse.ui.editors/plugin.properties @@ -47,7 +47,7 @@ ActionDefinition.quickDiff.revertLine.description= Revert the current line ActionDefinition.lineNumberToggle.name= Show Line Numbers ActionDefinition.lineNumberToggle.description= Toggle display of line numbers -Editors.DefaultTextEditor= Text Editor +Editors.DefaultTextEditor= Plain Text Editor PreferencePages.GeneralTextEditors= Text Editors PreferencePages.Annotations= Annotations PreferencePages.QuickDiff= Quick Diff diff --git a/bundles/org.eclipse.ui.ide/plugin.properties b/bundles/org.eclipse.ui.ide/plugin.properties index 8647371cf5a..6256c252eff 100644 --- a/bundles/org.eclipse.ui.ide/plugin.properties +++ b/bundles/org.eclipse.ui.ide/plugin.properties @@ -347,9 +347,9 @@ command.edit.delete.mnemonic = D command.edit.selectAll.mnemonic = A command.file.properties.mnemonic = P -systemEditorThenTextEditor=System Editor; if none: Text Editor +systemEditorThenTextEditor=System Editor; if none: Plain Text Editor askUserViaPopup=Ask via pop-up -textEditor=Text Editor +textEditor=Plain Text Editor # Smart Import ExtPoint.projectConfigurator=Project detector and configurator importProjectsFromFolder_command=Open Projects from File System... diff --git a/bundles/org.eclipse.ui.views.properties.tabbed/src/org/eclipse/ui/views/properties/tabbed/TabbedPropertySheetPage.java b/bundles/org.eclipse.ui.views.properties.tabbed/src/org/eclipse/ui/views/properties/tabbed/TabbedPropertySheetPage.java index 2117b2c7823..1512c9db525 100644 --- a/bundles/org.eclipse.ui.views.properties.tabbed/src/org/eclipse/ui/views/properties/tabbed/TabbedPropertySheetPage.java +++ b/bundles/org.eclipse.ui.views.properties.tabbed/src/org/eclipse/ui/views/properties/tabbed/TabbedPropertySheetPage.java @@ -332,8 +332,8 @@ protected void handlePartActivated(IWorkbenchPart part) { * for example, outline view. */ IContributedContentsView view = Adapters.adapt(part, IContributedContentsView.class); - if (!(view.getContributingPart() instanceof ITabbedPropertySheetPageContributor cp - && cp.equals(contributor))) { + if (view == null || (!(view.getContributingPart() instanceof ITabbedPropertySheetPageContributor cp + && cp.equals(contributor)))) { if (activePropertySheet) { if (currentTab != null) { currentTab.aboutToBeHidden(); diff --git a/bundles/org.eclipse.ui.views/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.views/META-INF/MANIFEST.MF index 711668e3508..7e7edf06b35 100644 --- a/bundles/org.eclipse.ui.views/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.ui.views/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.ui.views; singleton:=true -Bundle-Version: 3.12.400.qualifier +Bundle-Version: 3.12.500.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.ui.internal.views.contentoutline;x-internal:=true, diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java index 3ecc45e358d..258488084be 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java @@ -28,7 +28,6 @@ import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyListener; -import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; @@ -42,6 +41,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.swt.widgets.Scrollable; import org.eclipse.swt.widgets.Shell; @@ -204,7 +204,7 @@ public void controlResized(ControlEvent e) { } }; - private PaintListener widgetMovementListener = __ -> asyncExecIfOpen( + private Listener targetRelocationListener = __ -> asyncExecIfOpen( FindReplaceOverlay.this::updatePlacementAndVisibility); private void asyncExecIfOpen(Runnable operation) { @@ -423,7 +423,8 @@ private void unbindListeners() { Control targetWidget = textEditor.getAdapter(ITextViewer.class).getTextWidget(); if (targetWidget != null) { targetWidget.getShell().removeControlListener(shellMovementListener); - targetWidget.removePaintListener(widgetMovementListener); + targetWidget.removeListener(SWT.Move, targetRelocationListener); + targetWidget.removeListener(SWT.Resize, targetRelocationListener); targetWidget.removeKeyListener(closeOnTargetEscapeListener); targetPart.getSite().getPage().removePartListener(targetPartVisibilityHandler); } @@ -436,7 +437,8 @@ private void bindListeners() { Control targetWidget = textEditor.getAdapter(ITextViewer.class).getTextWidget(); targetWidget.getShell().addControlListener(shellMovementListener); - targetWidget.addPaintListener(widgetMovementListener); + targetWidget.addListener(SWT.Move, targetRelocationListener); + targetWidget.addListener(SWT.Resize, targetRelocationListener); targetWidget.addKeyListener(closeOnTargetEscapeListener); targetPart.getSite().getPage().addPartListener(targetPartVisibilityHandler); } @@ -975,7 +977,7 @@ private void updateFromTargetSelection() { findReplaceLogic.deactivate(SearchOptions.GLOBAL); searchInSelectionButton.setSelection(true); } else if (!selectionText.isEmpty()) { - if (findReplaceLogic.isAvailable(SearchOptions.REGEX)) { + if (findReplaceLogic.isAvailableAndActive(SearchOptions.REGEX)) { selectionText = FindReplaceDocumentAdapter.escapeForRegExPattern(selectionText); } searchBar.setText(selectionText); diff --git a/bundles/org.eclipse.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui/META-INF/MANIFEST.MF index 2d3229bd8ed..165143157ed 100644 --- a/bundles/org.eclipse.ui/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Plugin.name Bundle-SymbolicName: org.eclipse.ui; singleton:=true -Bundle-Version: 3.206.100.qualifier +Bundle-Version: 3.206.200.qualifier Bundle-Activator: org.eclipse.ui.internal.UIPlugin Bundle-ActivationPolicy: lazy Bundle-Vendor: %Plugin.providerName diff --git a/bundles/org.eclipse.urischeme/META-INF/MANIFEST.MF b/bundles/org.eclipse.urischeme/META-INF/MANIFEST.MF index cb9d7e714a3..a53634e3b88 100644 --- a/bundles/org.eclipse.urischeme/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.urischeme/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Plugin.name Bundle-SymbolicName: org.eclipse.urischeme;singleton:=true -Bundle-Version: 1.3.400.qualifier +Bundle-Version: 1.3.500.qualifier Automatic-Module-Name: org.eclipse.urischeme Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.8.0,4.0.0)", diff --git a/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/internal/registration/RegistrationMacOsX.java b/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/internal/registration/RegistrationMacOsX.java index 6b9f70475c8..2d31b2cb23f 100644 --- a/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/internal/registration/RegistrationMacOsX.java +++ b/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/internal/registration/RegistrationMacOsX.java @@ -35,7 +35,7 @@ public class RegistrationMacOsX implements IOperatingSystemRegistration { private IFileProvider fileProvider; private IProcessExecutor processExecutor; - private String lsRegisterOutput = null; + private String[] lsRegisterOutput = null; public RegistrationMacOsX() { this(new FileProvider(), new ProcessExecutor()); @@ -75,17 +75,15 @@ public List getSchemesInformation(Collection scheme return returnList; } - private String getLsRegisterOutput() throws Exception { + private String[] getLsRegisterOutput() throws Exception { if (this.lsRegisterOutput != null) { return this.lsRegisterOutput; } - this.lsRegisterOutput = processExecutor.execute(LSREGISTER, DUMP); + this.lsRegisterOutput = processExecutor.execute(LSREGISTER, DUMP).split("-".repeat(80) + "\n"); //$NON-NLS-1$//$NON-NLS-2$ return this.lsRegisterOutput; } - private String determineHandlerLocation(String lsRegisterDump, String scheme) { - - String[] lsRegisterEntries = lsRegisterDump.split("-{80}\n"); //$NON-NLS-1$ + private String determineHandlerLocation(String[] lsRegisterEntries, String scheme) { String keyOfFirstLine; String keyOfSchemeList; diff --git a/tests/org.eclipse.ui.editors.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.ui.editors.tests/META-INF/MANIFEST.MF index 140fd8f7b70..74a27a2c7f8 100644 --- a/tests/org.eclipse.ui.editors.tests/META-INF/MANIFEST.MF +++ b/tests/org.eclipse.ui.editors.tests/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Plugin.name Bundle-SymbolicName: org.eclipse.ui.editors.tests;singleton:=true -Bundle-Version: 3.13.500.qualifier +Bundle-Version: 3.13.600.qualifier Bundle-Vendor: %Plugin.providerName Bundle-Localization: plugin Export-Package: org.eclipse.jface.text.tests.codemining, diff --git a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandlerTest.java b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandlerTest.java index b10ee9ccfdd..3ac679d012f 100644 --- a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandlerTest.java +++ b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandlerTest.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.StringJoiner; +import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -75,6 +76,11 @@ public void setup() { stickyScrollingHandler = new StickyScrollingHandler(sourceViewer, ruler, store, linesProvider); } + @After + public void teardown() { + shell.dispose(); + } + @Test public void testShowStickyLines() { when(linesProvider.get(100, sourceViewer)).thenReturn(List.of(new StickyLine("line 10", 9))); @@ -129,13 +135,19 @@ public void testPreferencesUpdated() { @Test public void testThrottledExecution() throws InterruptedException { when(linesProvider.get(100, sourceViewer)).thenReturn(List.of(new StickyLine("line 10", 9))); + when(linesProvider.get(200, sourceViewer)).thenReturn(List.of(new StickyLine("line 10", 9))); + when(linesProvider.get(300, sourceViewer)).thenReturn(List.of(new StickyLine("line 10", 9))); + when(linesProvider.get(400, sourceViewer)).thenReturn(List.of(new StickyLine("line 10", 9))); stickyScrollingHandler.viewportChanged(100); + Thread.sleep(10); stickyScrollingHandler.viewportChanged(200); + Thread.sleep(10); stickyScrollingHandler.viewportChanged(300); + Thread.sleep(10); stickyScrollingHandler.viewportChanged(400); - waitInUi(200); + waitInUi(300); // Call to lines provider should be throttled verify(linesProvider, times(1)).get(100, sourceViewer); diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/ResourceInitialSelectionTest.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/ResourceInitialSelectionTest.java index 191115c4dd1..0ffe9d0be6e 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/ResourceInitialSelectionTest.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/dialogs/ResourceInitialSelectionTest.java @@ -14,7 +14,6 @@ package org.eclipse.ui.tests.dialogs; import static java.util.Arrays.asList; -import static org.junit.Assume.assumeFalse; import java.io.ByteArrayInputStream; import java.io.InputStream; @@ -23,6 +22,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import org.eclipse.core.resources.IFile; @@ -31,7 +31,6 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.Platform; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; @@ -288,7 +287,6 @@ public void testMultiSelectionAndSomeInitialNonExistingSelectionWithInitialPatte */ @Test public void testMultiSelectionAndTwoInitialSelectionsWithInitialPattern() { - assumeFalse("Test fails on Windows: Bug 559353", Platform.OS_WIN32.equals(Platform.getOS())); boolean hasMultiSelection = true; List initialSelection = asList(FILES.get("foo.txt"), FILES.get("bar.txt")); @@ -312,7 +310,6 @@ public void testMultiSelectionAndTwoInitialSelectionsWithInitialPattern() { */ @Test public void testMultiSelectionAndTwoInitialFilteredSelections() { - assumeFalse("Test fails on Windows: Bug 559353", Platform.OS_WIN32.equals(Platform.getOS())); boolean hasMultiSelection = true; @@ -383,7 +380,18 @@ protected void doTearDown() throws Exception { dialog.close(); } if (project != null) { - project.delete(true, null); + try { + project.delete(true, null); + } catch (Exception e) { + // try to get a stacktrace which jobs still has project open so that it can not + // be deleted: + for (Entry entry : Thread.getAllStackTraces().entrySet()) { + Exception exception = new Exception("ThreadDump for thread \"" + entry.getKey().getName() + "\""); + exception.setStackTrace(entry.getValue()); + e.addSuppressed(exception); + } + throw e; + } } super.doTearDown(); } diff --git a/tests/org.eclipse.ui.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.ui.tests/META-INF/MANIFEST.MF index 3005773519c..d1081e4f6d3 100644 --- a/tests/org.eclipse.ui.tests/META-INF/MANIFEST.MF +++ b/tests/org.eclipse.ui.tests/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Eclipse UI Tests Bundle-SymbolicName: org.eclipse.ui.tests; singleton:=true -Bundle-Version: 3.15.1700.qualifier +Bundle-Version: 3.15.1800.qualifier Eclipse-BundleShape: dir Bundle-Activator: org.eclipse.ui.tests.TestPlugin Bundle-Vendor: Eclipse.org diff --git a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/FindReplaceUITest.java b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/FindReplaceUITest.java index a2f674af0ab..6b3a0a4127a 100644 --- a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/FindReplaceUITest.java +++ b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/FindReplaceUITest.java @@ -119,7 +119,6 @@ public void testDisableWholeWordIfRegEx() { dialog.assertEnabled(SearchOptions.REGEX); dialog.assertEnabled(SearchOptions.WHOLE_WORD); - dialog.getFindReplaceLogic().updateTarget(fTextViewer.getFindReplaceTarget(), false); dialog.select(SearchOptions.WHOLE_WORD); dialog.select(SearchOptions.REGEX); dialog.assertEnabled(SearchOptions.REGEX); @@ -161,7 +160,7 @@ public void testShiftEnterReversesSearchDirection() { dialog.select(SearchOptions.INCREMENTAL); dialog.setFindText("line"); ensureHasFocusOnGTK(); - IFindReplaceTarget target= dialog.getTarget(); + IFindReplaceTarget target= getFindReplaceTarget(); assertEquals(0, (target.getSelection()).x); assertEquals(4, (target.getSelection()).y); @@ -190,7 +189,7 @@ public void testChangeInputForIncrementalSearch() { dialog.select(SearchOptions.INCREMENTAL); dialog.setFindText("lin"); - IFindReplaceTarget target= dialog.getTarget(); + IFindReplaceTarget target= getFindReplaceTarget(); assertEquals(0, (target.getSelection()).x); assertEquals(dialog.getFindText().length(), (target.getSelection()).y); @@ -206,7 +205,7 @@ public void testFindWithWholeWordEnabledWithMultipleWords() { dialog.select(SearchOptions.WHOLE_WORD); dialog.select(SearchOptions.WRAP); dialog.setFindText("two"); - IFindReplaceTarget target= dialog.getTarget(); + IFindReplaceTarget target= getFindReplaceTarget(); assertEquals(0, (target.getSelection()).x); assertEquals(3, (target.getSelection()).y); @@ -227,7 +226,7 @@ public void testRegExSearch() { dialog.select(SearchOptions.REGEX); dialog.setFindText("(a|bc)"); - IFindReplaceTarget target= dialog.getTarget(); + IFindReplaceTarget target= getFindReplaceTarget(); dialog.simulateKeyboardInteractionInFindInputField(SWT.CR, false); assertEquals(0, (target.getSelection()).x); assertEquals(1, (target.getSelection()).y); @@ -340,6 +339,18 @@ public void testSelectionOnOpenSetsScopedMode() { assertScopeActivationOnTextInput("hello\nworld"); } + @Test + public void testActivateDialogSelectionActive_withoutRegExOptionActivated() { + openTextViewer("test text.*;"); + initializeFindReplaceUIForTextViewer(); + + fTextViewer.setSelection(new TextSelection("test ".length(), "text.*".length())); + reopenFindReplaceUIForTextViewer(); + + dialog.assertUnselected(SearchOptions.REGEX); + assertEquals("text.*", dialog.getFindText()); + } + @Test public void testActivateDialogSelectionActive_withRegExOptionActivated() { openTextViewer("test text.*;"); @@ -374,4 +385,8 @@ protected TextViewer getTextViewer() { return fTextViewer; } + protected final IFindReplaceTarget getFindReplaceTarget() { + return fTextViewer.getFindReplaceTarget(); + } + } diff --git a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/IFindReplaceUIAccess.java b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/IFindReplaceUIAccess.java index 700bf25df04..57a4edd6f04 100644 --- a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/IFindReplaceUIAccess.java +++ b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/IFindReplaceUIAccess.java @@ -12,15 +12,11 @@ import org.eclipse.swt.widgets.Widget; -import org.eclipse.jface.text.IFindReplaceTarget; - /** * Wraps UI access for different find/replace UIs */ public interface IFindReplaceUIAccess { - IFindReplaceTarget getTarget(); - void closeAndRestore(); void close(); @@ -47,8 +43,6 @@ public interface IFindReplaceUIAccess { Widget getButtonForSearchOption(SearchOptions option); - IFindReplaceLogic getFindReplaceLogic(); - void performReplaceAll(); void performReplace(); diff --git a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlayTest.java b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlayTest.java index 51beb527d4a..58e7afc72d8 100644 --- a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlayTest.java +++ b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlayTest.java @@ -46,7 +46,7 @@ public OverlayAccess openUIFromTextViewer(TextViewer viewer) { Accessor actionAccessor= new Accessor(getFindReplaceAction(), FindReplaceAction.class); actionAccessor.invoke("showOverlayInEditor", null); Accessor overlayAccessor= new Accessor(actionAccessor.get("overlay"), "org.eclipse.ui.internal.findandreplace.overlay.FindReplaceOverlay", getClass().getClassLoader()); - return new OverlayAccess(overlayAccessor); + return new OverlayAccess(getFindReplaceTarget(), overlayAccessor); } @Test @@ -55,7 +55,7 @@ public void testDirectionalSearchButtons() { OverlayAccess dialog= getDialog(); dialog.setFindText("line"); - IFindReplaceTarget target= dialog.getTarget(); + IFindReplaceTarget target= getFindReplaceTarget(); assertEquals(0, (target.getSelection()).x); assertEquals(4, (target.getSelection()).y); @@ -89,14 +89,14 @@ public void testDirectionalSearchButtons() { public void testIncrementalSearchUpdatesAfterChangingOptions() { initializeTextViewerWithFindReplaceUI("alinee\naLinee\nline\nline"); OverlayAccess dialog= getDialog(); - IFindReplaceTarget target= dialog.getTarget(); + IFindReplaceTarget target= getFindReplaceTarget(); dialog.setFindText("Line"); - assertThat(dialog.getTarget().getSelectionText(), is("line")); - assertEquals(new Point(1,4), dialog.getTarget().getSelection()); + assertThat(target.getSelectionText(), is("line")); + assertEquals(new Point(1, 4), target.getSelection()); dialog.select(SearchOptions.CASE_SENSITIVE); - assertThat(dialog.getTarget().getSelectionText(), is("Line")); - assertEquals(new Point(8,4), dialog.getTarget().getSelection()); + assertThat(target.getSelectionText(), is("Line")); + assertEquals(new Point(8, 4), target.getSelection()); dialog.unselect(SearchOptions.CASE_SENSITIVE); assertEquals(1, (target.getSelection()).x); @@ -110,7 +110,7 @@ public void testIncrementalSearchUpdatesAfterChangingOptions() { dialog.unselect(SearchOptions.WHOLE_WORD); assertEquals(1, (target.getSelection()).x); assertEquals(4, (target.getSelection()).y); - assertThat(dialog.getTarget().getSelectionText(), is("line")); + assertThat(target.getSelectionText(), is("line")); } @Test @@ -153,18 +153,19 @@ public void testRememberReplaceExpandState() { @Test public void testSearchBackwardsWithRegEx() { initializeTextViewerWithFindReplaceUI("text text text"); + IFindReplaceTarget target= getFindReplaceTarget(); OverlayAccess dialog= getDialog(); dialog.select(SearchOptions.REGEX); dialog.setFindText("text"); // with RegEx enabled, there is no incremental search! dialog.pressSearch(true); - assertThat(dialog.getTarget().getSelection().y, is(4)); + assertThat(target.getSelection().y, is(4)); dialog.pressSearch(true); - assertThat(dialog.getTarget().getSelection().x, is("text ".length())); + assertThat(target.getSelection().x, is("text ".length())); dialog.pressSearch(true); - assertThat(dialog.getTarget().getSelection().x, is("text text ".length())); + assertThat(target.getSelection().x, is("text text ".length())); dialog.pressSearch(false); - assertThat(dialog.getTarget().getSelection().x, is("text ".length())); + assertThat(target.getSelection().x, is("text ".length())); } @Test diff --git a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/overlay/OverlayAccess.java b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/overlay/OverlayAccess.java index 2d4896e9317..ae961a3e0da 100644 --- a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/overlay/OverlayAccess.java +++ b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/internal/findandreplace/overlay/OverlayAccess.java @@ -36,45 +36,43 @@ import org.eclipse.jface.text.IFindReplaceTarget; import org.eclipse.jface.text.IFindReplaceTargetExtension; -import org.eclipse.ui.internal.findandreplace.FindReplaceLogic; -import org.eclipse.ui.internal.findandreplace.IFindReplaceLogic; import org.eclipse.ui.internal.findandreplace.IFindReplaceUIAccess; import org.eclipse.ui.internal.findandreplace.SearchOptions; class OverlayAccess implements IFindReplaceUIAccess { - FindReplaceLogic findReplaceLogic; + private final IFindReplaceTarget findReplaceTarget; - HistoryTextWrapper find; + private final HistoryTextWrapper find; - HistoryTextWrapper replace; + private final ToolItem inSelection; - ToolItem inSelection; + private final ToolItem caseSensitive; - ToolItem caseSensitive; + private final ToolItem wholeWord; - ToolItem wholeWord; + private final ToolItem regEx; - ToolItem regEx; + private final ToolItem searchForward; - ToolItem searchForward; + private final ToolItem searchBackward; - ToolItem searchBackward; + private final Button openReplaceDialog; - Button openReplaceDialog; + private HistoryTextWrapper replace; - ToolItem replaceButton; + private ToolItem replaceButton; - ToolItem replaceAllButton; + private ToolItem replaceAllButton; - private Runnable closeOperation; + private final Runnable closeOperation; - Accessor dialogAccessor; + private final Accessor dialogAccessor; - private Supplier shellRetriever; + private final Supplier shellRetriever; - OverlayAccess(Accessor findReplaceOverlayAccessor) { + OverlayAccess(IFindReplaceTarget findReplaceTarget, Accessor findReplaceOverlayAccessor) { + this.findReplaceTarget= findReplaceTarget; dialogAccessor= findReplaceOverlayAccessor; - findReplaceLogic= (FindReplaceLogic) findReplaceOverlayAccessor.get("findReplaceLogic"); find= (HistoryTextWrapper) findReplaceOverlayAccessor.get("searchBar"); replace= (HistoryTextWrapper) findReplaceOverlayAccessor.get("replaceBar"); caseSensitive= (ToolItem) findReplaceOverlayAccessor.get("caseSensitiveSearchButton"); @@ -90,11 +88,6 @@ class OverlayAccess implements IFindReplaceUIAccess { shellRetriever= () -> ((Shell) findReplaceOverlayAccessor.invoke("getShell", null)); } - @Override - public IFindReplaceTarget getTarget() { - return findReplaceLogic.getTarget(); - } - private void restoreInitialConfiguration() { find.setText(""); select(SearchOptions.GLOBAL); @@ -228,11 +221,6 @@ public void pressSearch(boolean forward) { } } - @Override - public IFindReplaceLogic getFindReplaceLogic() { - return findReplaceLogic; - } - @Override public void performReplaceAll() { openReplaceDialog(); @@ -277,25 +265,23 @@ public void assertInitialConfiguration() { assertUnselected(SearchOptions.REGEX); assertUnselected(SearchOptions.WHOLE_WORD); assertUnselected(SearchOptions.CASE_SENSITIVE); - if (!doesTextViewerHaveMultiLineSelection(findReplaceLogic.getTarget())) { + if (!doesTextViewerHaveMultiLineSelection()) { assertSelected(SearchOptions.GLOBAL); - assertTrue(findReplaceLogic.isActive(SearchOptions.GLOBAL)); } else { assertUnselected(SearchOptions.GLOBAL); - assertFalse(findReplaceLogic.isActive(SearchOptions.GLOBAL)); } assertEnabled(SearchOptions.GLOBAL); assertEnabled(SearchOptions.REGEX); assertEnabled(SearchOptions.CASE_SENSITIVE); - if (getFindText().equals("") || findReplaceLogic.isAvailable(SearchOptions.WHOLE_WORD)) { + if (!getFindText().contains(" ")) { assertEnabled(SearchOptions.WHOLE_WORD); } else { assertDisabled(SearchOptions.WHOLE_WORD); } } - private boolean doesTextViewerHaveMultiLineSelection(IFindReplaceTarget target) { - if (target instanceof IFindReplaceTargetExtension scopeProvider) { + private boolean doesTextViewerHaveMultiLineSelection() { + if (findReplaceTarget instanceof IFindReplaceTargetExtension scopeProvider) { return scopeProvider.getScope() != null; // null is returned for global scope } return false; diff --git a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/DialogAccess.java b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/DialogAccess.java index bbbd0b507bc..453e1f84317 100644 --- a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/DialogAccess.java +++ b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/DialogAccess.java @@ -15,7 +15,6 @@ import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.Set; @@ -34,14 +33,12 @@ import org.eclipse.jface.text.IFindReplaceTarget; import org.eclipse.jface.text.IFindReplaceTargetExtension; -import org.eclipse.ui.internal.findandreplace.FindReplaceLogic; -import org.eclipse.ui.internal.findandreplace.IFindReplaceLogic; import org.eclipse.ui.internal.findandreplace.IFindReplaceUIAccess; import org.eclipse.ui.internal.findandreplace.SearchOptions; class DialogAccess implements IFindReplaceUIAccess { - FindReplaceLogic findReplaceLogic; + private final IFindReplaceTarget findReplaceTarget; Combo findCombo; @@ -77,9 +74,9 @@ class DialogAccess implements IFindReplaceUIAccess { Accessor dialogAccessor; - DialogAccess(Accessor findReplaceDialogAccessor) { + DialogAccess(IFindReplaceTarget findReplaceTarget, Accessor findReplaceDialogAccessor) { + this.findReplaceTarget= findReplaceTarget; dialogAccessor= findReplaceDialogAccessor; - findReplaceLogic= (FindReplaceLogic) findReplaceDialogAccessor.get("findReplaceLogic"); findCombo= (Combo) findReplaceDialogAccessor.get("fFindField"); replaceCombo= (Combo) findReplaceDialogAccessor.get("fReplaceField"); forwardRadioButton= (Button) findReplaceDialogAccessor.get("fForwardRadioButton"); @@ -199,11 +196,6 @@ public void setReplaceText(String text) { replaceCombo.notifyListeners(SWT.Modify, null); } - @Override - public IFindReplaceTarget getTarget() { - return findReplaceLogic.getTarget(); - } - @Override public String getFindText() { return findCombo.getText(); @@ -219,11 +211,6 @@ public Combo getFindCombo() { return findCombo; } - @Override - public IFindReplaceLogic getFindReplaceLogic() { - return findReplaceLogic; - } - @Override public void performReplaceAll() { replaceAllButton.notifyListeners(SWT.Selection, null); @@ -241,20 +228,11 @@ public void performReplaceAndFind() { @Override public void assertInitialConfiguration() { - assertTrue(findReplaceLogic.isActive(SearchOptions.FORWARD)); - assertFalse(findReplaceLogic.isActive(SearchOptions.CASE_SENSITIVE)); - assertTrue(findReplaceLogic.isActive(SearchOptions.WRAP)); - assertFalse(findReplaceLogic.isActive(SearchOptions.INCREMENTAL)); - assertFalse(findReplaceLogic.isActive(SearchOptions.REGEX)); - assertFalse(findReplaceLogic.isActive(SearchOptions.WHOLE_WORD)); - assertSelected(SearchOptions.FORWARD); - if (!doesTextViewerHaveMultiLineSelection(findReplaceLogic.getTarget())) { + if (!doesTextViewerHaveMultiLineSelection(findReplaceTarget)) { assertSelected(SearchOptions.GLOBAL); - assertTrue(findReplaceLogic.isActive(SearchOptions.GLOBAL)); } else { assertUnselected(SearchOptions.GLOBAL); - assertFalse(findReplaceLogic.isActive(SearchOptions.GLOBAL)); } assertSelected(SearchOptions.WRAP); diff --git a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/FindReplaceDialogTest.java b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/FindReplaceDialogTest.java index e9ace137e2d..f6a992264e7 100644 --- a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/FindReplaceDialogTest.java +++ b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/FindReplaceDialogTest.java @@ -51,7 +51,7 @@ public DialogAccess openUIFromTextViewer(TextViewer viewer) { Accessor fFindReplaceDialogStubAccessor= new Accessor(fFindReplaceDialogStub, "org.eclipse.ui.texteditor.FindReplaceAction$FindReplaceDialogStub", getClass().getClassLoader()); Accessor dialogAccessor= new Accessor(fFindReplaceDialogStubAccessor.invoke("getDialog", null), "org.eclipse.ui.texteditor.FindReplaceDialog", getClass().getClassLoader()); - return new DialogAccess(dialogAccessor); + return new DialogAccess(getFindReplaceTarget(), dialogAccessor); } @Test @@ -122,7 +122,7 @@ public void testShiftEnterReversesSearchDirectionDialogSpecific() { dialog.setFindText("line"); ensureHasFocusOnGTK(); - IFindReplaceTarget target= dialog.getTarget(); + IFindReplaceTarget target= getFindReplaceTarget(); dialog.simulateKeyboardInteractionInFindInputField(SWT.CR, false); assertEquals(0, (target.getSelection()).x); @@ -152,7 +152,7 @@ public void testReplaceAndFindAfterInitializingFindWithSelectedString() { assertThat(dialog.getFindText(), is("text")); - IFindReplaceTarget target= dialog.getTarget(); + IFindReplaceTarget target= getFindReplaceTarget(); assertEquals(0, (target.getSelection()).x); assertEquals(4, (target.getSelection()).y); @@ -209,7 +209,7 @@ public void testFindWithWholeWordEnabledWithMultipleWordsNotIncremental() { dialog.setFindText("two"); dialog.select(SearchOptions.WHOLE_WORD); dialog.select(SearchOptions.WRAP); - IFindReplaceTarget target= dialog.getTarget(); + IFindReplaceTarget target= getFindReplaceTarget(); dialog.simulateKeyboardInteractionInFindInputField(SWT.CR, false); assertEquals(0, (target.getSelection()).x);