| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.ui.search; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.accessibility.ACC; |
| import org.eclipse.swt.accessibility.AccessibleAdapter; |
| import org.eclipse.swt.accessibility.AccessibleEvent; |
| import org.eclipse.swt.events.ModifyEvent; |
| import org.eclipse.swt.events.ModifyListener; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Combo; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Group; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Link; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.IAdaptable; |
| |
| import org.eclipse.core.resources.IFile; |
| |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.dialogs.DialogPage; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.window.Window; |
| |
| import org.eclipse.jface.text.ITextSelection; |
| |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.IWorkingSet; |
| import org.eclipse.ui.IWorkingSetManager; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.model.IWorkbenchAdapter; |
| |
| import org.eclipse.search.ui.ISearchPage; |
| import org.eclipse.search.ui.ISearchPageContainer; |
| import org.eclipse.search.ui.NewSearchUI; |
| |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IField; |
| import org.eclipse.jdt.core.IImportDeclaration; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.IModularClassFile; |
| import org.eclipse.jdt.core.IModuleDescription; |
| import org.eclipse.jdt.core.IOrdinaryClassFile; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.Signature; |
| import org.eclipse.jdt.core.formatter.IndentManipulation; |
| import org.eclipse.jdt.core.search.IJavaSearchConstants; |
| import org.eclipse.jdt.core.search.IJavaSearchScope; |
| import org.eclipse.jdt.core.search.SearchPattern; |
| |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| |
| import org.eclipse.jdt.ui.search.ElementQuerySpecification; |
| import org.eclipse.jdt.ui.search.PatternQuerySpecification; |
| import org.eclipse.jdt.ui.search.QuerySpecification; |
| |
| import org.eclipse.jdt.internal.ui.IJavaHelpContextIds; |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.actions.SelectionConverter; |
| import org.eclipse.jdt.internal.ui.browsing.LogicalPackage; |
| import org.eclipse.jdt.internal.ui.dialogs.TextFieldNavigationHandler; |
| import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; |
| import org.eclipse.jdt.internal.ui.search.MatchLocations.MatchLocationSelectionDialog; |
| import org.eclipse.jdt.internal.ui.util.ExceptionHandler; |
| import org.eclipse.jdt.internal.ui.util.SWTUtil; |
| |
| public class JavaSearchPage extends DialogPage implements ISearchPage { |
| |
| private static class SearchPatternData { |
| private final int searchFor; |
| private final int limitTo; |
| private final String pattern; |
| private final boolean isCaseSensitive; |
| private final int includeMask; |
| private final int matchLocations; |
| private final int scope; |
| private final IWorkingSet[] workingSets; |
| private IJavaElement javaElement; |
| |
| public SearchPatternData(int searchFor, int limitTo, int matchLocations, boolean isCaseSensitive, String pattern, IJavaElement element, int includeMask) { |
| this(searchFor, limitTo, matchLocations, pattern, isCaseSensitive, element, ISearchPageContainer.WORKSPACE_SCOPE, null, includeMask); |
| } |
| |
| public SearchPatternData(int searchFor, int limitTo, int matchLocations, String pattern, boolean isCaseSensitive, IJavaElement element, int scope, IWorkingSet[] workingSets, int includeMask) { |
| this.searchFor= searchFor; |
| this.limitTo= limitTo; |
| this.matchLocations= matchLocations; |
| this.pattern= pattern; |
| this.isCaseSensitive= isCaseSensitive; |
| this.scope= scope; |
| this.workingSets= workingSets; |
| this.includeMask= includeMask; |
| |
| setJavaElement(element); |
| } |
| |
| public void setJavaElement(IJavaElement javaElement) { |
| this.javaElement= javaElement; |
| } |
| |
| public boolean isCaseSensitive() { |
| return isCaseSensitive; |
| } |
| |
| public IJavaElement getJavaElement() { |
| return javaElement; |
| } |
| |
| public int getLimitTo() { |
| return limitTo; |
| } |
| |
| public String getPattern() { |
| return pattern; |
| } |
| |
| public int getScope() { |
| return scope; |
| } |
| |
| public int getSearchFor() { |
| return searchFor; |
| } |
| |
| public IWorkingSet[] getWorkingSets() { |
| return workingSets; |
| } |
| |
| public int getIncludeMask() { |
| return includeMask; |
| } |
| |
| public int getMatchLocations() { |
| return matchLocations; |
| } |
| |
| public void store(IDialogSettings settings) { |
| settings.put("searchFor", searchFor); //$NON-NLS-1$ |
| settings.put("scope", scope); //$NON-NLS-1$ |
| settings.put("pattern", pattern); //$NON-NLS-1$ |
| settings.put("limitTo", limitTo); //$NON-NLS-1$ |
| settings.put("matchLocations", matchLocations); //$NON-NLS-1$ |
| settings.put("javaElement", javaElement != null ? javaElement.getHandleIdentifier() : ""); //$NON-NLS-1$ //$NON-NLS-2$ |
| settings.put("isCaseSensitive", isCaseSensitive); //$NON-NLS-1$ |
| if (workingSets != null) { |
| String[] wsIds= new String[workingSets.length]; |
| for (int i= 0; i < workingSets.length; i++) { |
| wsIds[i]= workingSets[i].getName(); |
| } |
| settings.put("workingSets", wsIds); //$NON-NLS-1$ |
| } else { |
| settings.put("workingSets", new String[0]); //$NON-NLS-1$ |
| } |
| settings.put("includeMask", includeMask); //$NON-NLS-1$ |
| } |
| |
| public static SearchPatternData create(IDialogSettings settings) { |
| String pattern= settings.get("pattern"); //$NON-NLS-1$ |
| if (pattern.length() == 0) { |
| return null; |
| } |
| IJavaElement elem= null; |
| String handleId= settings.get("javaElement"); //$NON-NLS-1$ |
| if (handleId != null && handleId.length() > 0) { |
| IJavaElement restored= JavaCore.create(handleId); |
| if (restored != null && isSearchableType(restored) && restored.exists()) { |
| elem= restored; |
| } |
| } |
| String[] wsIds= settings.getArray("workingSets"); //$NON-NLS-1$ |
| IWorkingSet[] workingSets= null; |
| if (wsIds != null && wsIds.length > 0) { |
| IWorkingSetManager workingSetManager= PlatformUI.getWorkbench().getWorkingSetManager(); |
| workingSets= new IWorkingSet[wsIds.length]; |
| for (int i= 0; workingSets != null && i < wsIds.length; i++) { |
| workingSets[i]= workingSetManager.getWorkingSet(wsIds[i]); |
| if (workingSets[i] == null) { |
| workingSets= null; |
| } |
| } |
| } |
| |
| try { |
| int searchFor= settings.getInt("searchFor"); //$NON-NLS-1$ |
| int scope= settings.getInt("scope"); //$NON-NLS-1$ |
| int limitTo= settings.getInt("limitTo"); //$NON-NLS-1$ |
| |
| int matchLocations= 0; |
| if (settings.get("matchLocations") != null) { //$NON-NLS-1$ |
| matchLocations= settings.getInt("matchLocations"); //$NON-NLS-1$ |
| } |
| |
| boolean isCaseSensitive= settings.getBoolean("isCaseSensitive"); //$NON-NLS-1$ |
| |
| int includeMask; |
| if (settings.get("includeMask") != null) { //$NON-NLS-1$ |
| includeMask= settings.getInt("includeMask"); //$NON-NLS-1$ |
| } else { |
| includeMask= JavaSearchScopeFactory.NO_JRE; |
| if (settings.get("includeJRE") == null ? forceIncludeAll(limitTo, elem) : settings.getBoolean("includeJRE")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| includeMask= JavaSearchScopeFactory.ALL; |
| } |
| } |
| return new SearchPatternData(searchFor, limitTo, matchLocations, pattern, isCaseSensitive, elem, scope, workingSets, includeMask); |
| } catch (NumberFormatException e) { |
| return null; |
| } |
| } |
| |
| } |
| |
| // search for |
| private final static int TYPE= IJavaSearchConstants.TYPE; |
| private final static int METHOD= IJavaSearchConstants.METHOD; |
| private final static int PACKAGE= IJavaSearchConstants.PACKAGE; |
| private final static int CONSTRUCTOR= IJavaSearchConstants.CONSTRUCTOR; |
| private final static int MODULE= IJavaSearchConstants.MODULE; |
| private final static int FIELD= IJavaSearchConstants.FIELD; |
| |
| // limit to |
| private final static int DECLARATIONS= IJavaSearchConstants.DECLARATIONS; |
| private final static int IMPLEMENTORS= IJavaSearchConstants.IMPLEMENTORS; |
| private final static int REFERENCES= IJavaSearchConstants.REFERENCES; |
| private final static int SPECIFIC_REFERENCES= IJavaSearchConstants.CAST_TYPE_REFERENCE; |
| private final static int ALL_OCCURRENCES= IJavaSearchConstants.ALL_OCCURRENCES; |
| private final static int READ_ACCESSES= IJavaSearchConstants.READ_ACCESSES; |
| private final static int WRITE_ACCESSES= IJavaSearchConstants.WRITE_ACCESSES; |
| |
| public static final String PARTICIPANT_EXTENSION_POINT= "org.eclipse.jdt.ui.queryParticipants"; //$NON-NLS-1$ |
| |
| public static final String EXTENSION_POINT_ID= "org.eclipse.jdt.ui.JavaSearchPage"; //$NON-NLS-1$ |
| |
| private static final int HISTORY_SIZE= 12; |
| |
| // Dialog store id constants |
| private final static String PAGE_NAME= "JavaSearchPage"; //$NON-NLS-1$ |
| private final static String STORE_CASE_SENSITIVE= "CASE_SENSITIVE"; //$NON-NLS-1$ |
| private final static String STORE_INCLUDE_MASK= "INCLUDE_MASK"; //$NON-NLS-1$ |
| private final static String STORE_HISTORY= "HISTORY"; //$NON-NLS-1$ |
| private final static String STORE_HISTORY_SIZE= "HISTORY_SIZE"; //$NON-NLS-1$ |
| |
| private final List<SearchPatternData> fPreviousSearchPatterns; |
| |
| private SearchPatternData fInitialData; |
| private IJavaElement fJavaElement; |
| private boolean fFirstTime= true; |
| private IDialogSettings fDialogSettings; |
| private boolean fIsCaseSensitive; |
| |
| private Combo fPattern; |
| private ISearchPageContainer fContainer; |
| private Button fCaseSensitive; |
| |
| private Button[] fSearchFor; |
| private Button[] fLimitTo; |
| private Button[] fIncludeMasks; |
| private Group fLimitToGroup; |
| |
| private int fMatchLocations; |
| private Link fMatchLocationsLink; |
| |
| /** |
| * |
| */ |
| public JavaSearchPage() { |
| fPreviousSearchPatterns= new ArrayList<>(); |
| } |
| |
| |
| //---- Action Handling ------------------------------------------------ |
| |
| @Override |
| public boolean performAction() { |
| return performNewSearch(); |
| } |
| |
| private boolean performNewSearch() { |
| SearchPatternData data= getPatternData(); |
| |
| // Setup search scope |
| IJavaSearchScope scope= null; |
| String scopeDescription= ""; //$NON-NLS-1$ |
| |
| int searchFor= data.getSearchFor(); |
| int limitTo= data.getLimitTo(); |
| if (limitTo == SPECIFIC_REFERENCES) { |
| limitTo= fMatchLocations; |
| } |
| |
| int includeMask= data.getIncludeMask(); |
| JavaSearchScopeFactory factory= JavaSearchScopeFactory.getInstance(); |
| |
| switch (getContainer().getSelectedScope()) { |
| case ISearchPageContainer.WORKSPACE_SCOPE: |
| scopeDescription= factory.getWorkspaceScopeDescription(includeMask); |
| scope= factory.createWorkspaceScope(includeMask); |
| break; |
| case ISearchPageContainer.SELECTION_SCOPE: |
| IJavaElement[] javaElements= new IJavaElement[0]; |
| if (getContainer().getActiveEditorInput() != null) { |
| IFile file= getContainer().getActiveEditorInput().getAdapter(IFile.class); |
| if (file != null && file.exists()) { |
| IJavaElement javaElement= JavaCore.create(file); |
| if (javaElement != null) |
| javaElements= new IJavaElement[] { javaElement }; |
| } |
| } else |
| javaElements= factory.getJavaElements(getContainer().getSelection()); |
| scope= factory.createJavaSearchScope(javaElements, includeMask); |
| scopeDescription= factory.getSelectionScopeDescription(javaElements, includeMask); |
| break; |
| case ISearchPageContainer.SELECTED_PROJECTS_SCOPE: { |
| String[] projectNames= getContainer().getSelectedProjectNames(); |
| scope= factory.createJavaProjectSearchScope(projectNames, includeMask); |
| scopeDescription= factory.getProjectScopeDescription(projectNames, includeMask); |
| break; |
| } |
| case ISearchPageContainer.WORKING_SET_SCOPE: { |
| IWorkingSet[] workingSets= getContainer().getSelectedWorkingSets(); |
| // should not happen - just to be sure |
| if (workingSets == null || workingSets.length < 1) |
| return false; |
| scopeDescription= factory.getWorkingSetScopeDescription(workingSets, includeMask); |
| scope= factory.createJavaSearchScope(workingSets, includeMask); |
| SearchUtil.updateLRUWorkingSets(workingSets); |
| } |
| } |
| |
| QuerySpecification querySpec= null; |
| if (data.getJavaElement() != null && getPattern().equals(fInitialData.getPattern())) { |
| if (limitTo == REFERENCES) |
| SearchUtil.warnIfBinaryConstant(data.getJavaElement(), getShell()); |
| querySpec= new ElementQuerySpecification(data.getJavaElement(), limitTo, scope, scopeDescription); |
| } else { |
| querySpec= new PatternQuerySpecification(data.getPattern(), searchFor, data.isCaseSensitive(), limitTo, scope, scopeDescription); |
| data.setJavaElement(null); |
| } |
| |
| JavaSearchQuery textSearchJob= new JavaSearchQuery(querySpec); |
| NewSearchUI.runQueryInBackground(textSearchJob); |
| return true; |
| } |
| |
| private int getLimitTo() { |
| for (Button button : fLimitTo) { |
| if (button.getSelection()) { |
| return getIntData(button); |
| } |
| } |
| return -1; |
| } |
| |
| private int setLimitTo(int searchFor, int limitTo) { |
| if (searchFor != TYPE && limitTo == IMPLEMENTORS) { |
| limitTo= REFERENCES; |
| } |
| |
| if (searchFor != FIELD && (limitTo == READ_ACCESSES || limitTo == WRITE_ACCESSES)) { |
| limitTo= REFERENCES; |
| } |
| |
| if (searchFor != TYPE /*&& searchFor != FIELD*/ && searchFor != METHOD && searchFor != CONSTRUCTOR && limitTo == SPECIFIC_REFERENCES) { |
| limitTo= REFERENCES; |
| } |
| fillLimitToGroup(searchFor, limitTo); |
| return limitTo; |
| } |
| |
| private int getIncludeMask() { |
| int mask= 0; |
| for (Button button : fIncludeMasks) { |
| if (button.getSelection()) { |
| mask |= getIntData(button); |
| } |
| } |
| return mask; |
| } |
| |
| private void setIncludeMask(int includeMask) { |
| for (Button button : fIncludeMasks) { |
| button.setSelection((includeMask & getIntData(button)) != 0); |
| } |
| } |
| |
| private void setMatchLocations(int matchLocations) { |
| fMatchLocations= matchLocations; |
| updateMatchLocationText(); |
| } |
| |
| private String[] getPreviousSearchPatterns() { |
| // Search results are not persistent |
| int patternCount= fPreviousSearchPatterns.size(); |
| String [] patterns= new String[patternCount]; |
| for (int i= 0; i < patternCount; i++) |
| patterns[i]= fPreviousSearchPatterns.get(i).getPattern(); |
| return patterns; |
| } |
| |
| private int getSearchFor() { |
| for (Button button : fSearchFor) { |
| if (button.getSelection()) { |
| return getIntData(button); |
| } |
| } |
| Assert.isTrue(false, "shouldNeverHappen"); //$NON-NLS-1$ |
| return -1; |
| } |
| |
| private void setSearchFor(int searchFor) { |
| for (Button button : fSearchFor) { |
| button.setSelection(searchFor == getIntData(button)); |
| } |
| } |
| |
| private int getIntData(Button button) { |
| return ((Integer) button.getData()).intValue(); |
| } |
| |
| private String getPattern() { |
| return fPattern.getText(); |
| } |
| |
| |
| private SearchPatternData findInPrevious(String pattern) { |
| for (SearchPatternData element : fPreviousSearchPatterns) { |
| if (pattern.equals(element.getPattern())) { |
| return element; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Return search pattern data and update previous searches. |
| * An existing entry will be updated. |
| * @return the pattern data |
| */ |
| private SearchPatternData getPatternData() { |
| String pattern= getPattern(); |
| SearchPatternData match= findInPrevious(pattern); |
| if (match != null) { |
| fPreviousSearchPatterns.remove(match); |
| } |
| match= new SearchPatternData( |
| getSearchFor(), |
| getLimitTo(), |
| fMatchLocations, |
| pattern, |
| fCaseSensitive.getSelection(), |
| fJavaElement, |
| getContainer().getSelectedScope(), |
| getContainer().getSelectedWorkingSets(), |
| getIncludeMask() |
| ); |
| |
| fPreviousSearchPatterns.add(0, match); // insert on top |
| return match; |
| } |
| |
| /* |
| * Implements method from IDialogPage |
| */ |
| @Override |
| public void setVisible(boolean visible) { |
| if (visible && fPattern != null) { |
| if (fFirstTime) { |
| fFirstTime= false; |
| // Set item and text here to prevent page from resizing |
| fPattern.setItems(getPreviousSearchPatterns()); |
| initSelections(); |
| } |
| fPattern.setFocus(); |
| } |
| updateOKStatus(); |
| |
| IEditorInput editorInput= getContainer().getActiveEditorInput(); |
| getContainer().setActiveEditorCanProvideScopeSelection(editorInput != null && editorInput.getAdapter(IFile.class) != null); |
| |
| super.setVisible(visible); |
| } |
| |
| public boolean isValid() { |
| return true; |
| } |
| |
| //---- Widget creation ------------------------------------------------ |
| |
| |
| @Override |
| public void createControl(Composite parent) { |
| initializeDialogUnits(parent); |
| readConfiguration(); |
| |
| Composite result= new Composite(parent, SWT.NONE); |
| |
| GridLayout layout= new GridLayout(2, true); |
| layout.horizontalSpacing= 10; |
| result.setLayout(layout); |
| |
| Control expressionComposite= createExpression(result); |
| expressionComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1)); |
| |
| Label separator= new Label(result, SWT.NONE); |
| separator.setVisible(false); |
| GridData data= new GridData(GridData.FILL, GridData.FILL, false, false, 2, 1); |
| data.heightHint= convertHeightInCharsToPixels(1) / 3; |
| separator.setLayoutData(data); |
| |
| Control searchFor= createSearchFor(result); |
| searchFor.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1)); |
| |
| Control limitTo= createLimitTo(result); |
| limitTo.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1)); |
| |
| Control includeMask= createIncludeMask(result); |
| includeMask.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 2, 1)); |
| |
| //createParticipants(result); |
| |
| SelectionAdapter javaElementInitializer= new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent event) { |
| if (getSearchFor() == fInitialData.getSearchFor()) |
| fJavaElement= fInitialData.getJavaElement(); |
| else |
| fJavaElement= null; |
| setLimitTo(getSearchFor(), getLimitTo()); |
| setIncludeMask(getIncludeMask()); |
| doPatternModified(); |
| } |
| }; |
| |
| for (Button b : fSearchFor) { |
| b.addSelectionListener(javaElementInitializer); |
| } |
| |
| setControl(result); |
| |
| Dialog.applyDialogFont(result); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(result, IJavaHelpContextIds.JAVA_SEARCH_PAGE); |
| } |
| |
| |
| /*private Control createParticipants(Composite result) { |
| if (!SearchParticipantsExtensionPoint.hasAnyParticipants()) |
| return new Composite(result, SWT.NULL); |
| Button selectParticipants= new Button(result, SWT.PUSH); |
| selectParticipants.setText(SearchMessages.getString("SearchPage.select_participants.label")); //$NON-NLS-1$ |
| GridData gd= new GridData(); |
| gd.verticalAlignment= GridData.VERTICAL_ALIGN_BEGINNING; |
| gd.horizontalAlignment= GridData.HORIZONTAL_ALIGN_END; |
| gd.grabExcessHorizontalSpace= false; |
| gd.horizontalAlignment= GridData.END; |
| gd.horizontalSpan= 2; |
| selectParticipants.setLayoutData(gd); |
| selectParticipants.addSelectionListener(new SelectionAdapter() { |
| public void widgetSelected(SelectionEvent e) { |
| PreferencePageSupport.showPreferencePage(getShell(), "org.eclipse.jdt.ui.preferences.SearchParticipantsExtensionPoint", new SearchParticipantsExtensionPoint()); //$NON-NLS-1$ |
| } |
| |
| }); |
| return selectParticipants; |
| }*/ |
| |
| |
| private Control createExpression(Composite parent) { |
| Composite result= new Composite(parent, SWT.NONE); |
| GridLayout layout= new GridLayout(2, false); |
| layout.marginWidth= 0; |
| layout.marginHeight= 0; |
| result.setLayout(layout); |
| |
| // Pattern text + info |
| Label label= new Label(result, SWT.LEFT); |
| label.setText(SearchMessages.SearchPage_expression_label); |
| label.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false, 2, 1)); |
| |
| // Pattern combo |
| fPattern= new Combo(result, SWT.SINGLE | SWT.BORDER); |
| SWTUtil.setDefaultVisibleItemCount(fPattern); |
| fPattern.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| handlePatternSelected(); |
| updateOKStatus(); |
| } |
| }); |
| fPattern.addModifyListener(new ModifyListener() { |
| @Override |
| public void modifyText(ModifyEvent e) { |
| doPatternModified(); |
| updateOKStatus(); |
| |
| } |
| }); |
| TextFieldNavigationHandler.install(fPattern); |
| GridData data= new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1); |
| data.widthHint= convertWidthInCharsToPixels(50); |
| fPattern.setLayoutData(data); |
| |
| // Ignore case checkbox |
| fCaseSensitive= new Button(result, SWT.CHECK); |
| fCaseSensitive.setText(SearchMessages.SearchPage_expression_caseSensitive); |
| fCaseSensitive.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| fIsCaseSensitive= fCaseSensitive.getSelection(); |
| } |
| }); |
| fCaseSensitive.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false, 1, 1)); |
| |
| return result; |
| } |
| |
| final void updateOKStatus() { |
| boolean isValidPattern= isValidSearchPattern(); |
| boolean isValidMask= getIncludeMask() != 0; |
| getContainer().setPerformActionEnabled(isValidPattern && isValidMask); |
| } |
| |
| private boolean isValidSearchPattern() { |
| if (getPattern().length() == 0) { |
| return false; |
| } |
| if (fJavaElement != null) { |
| return true; |
| } |
| return SearchPattern.createPattern(getPattern(), getSearchFor(), getLimitTo(), SearchPattern.R_EXACT_MATCH) != null; |
| } |
| |
| |
| @Override |
| public void dispose() { |
| writeConfiguration(); |
| super.dispose(); |
| } |
| |
| private void doPatternModified() { |
| if (fInitialData != null && getPattern().equals(fInitialData.getPattern()) && fInitialData.getJavaElement() != null && fInitialData.getSearchFor() == getSearchFor()) { |
| fCaseSensitive.setEnabled(false); |
| fCaseSensitive.setSelection(true); |
| fJavaElement= fInitialData.getJavaElement(); |
| } else { |
| fCaseSensitive.setEnabled(true); |
| fCaseSensitive.setSelection(fIsCaseSensitive); |
| fJavaElement= null; |
| } |
| } |
| |
| private void handlePatternSelected() { |
| int selectionIndex= fPattern.getSelectionIndex(); |
| if (selectionIndex < 0 || selectionIndex >= fPreviousSearchPatterns.size()) |
| return; |
| |
| SearchPatternData initialData= fPreviousSearchPatterns.get(selectionIndex); |
| |
| setSearchFor(initialData.getSearchFor()); |
| setLimitTo(initialData.getSearchFor(), initialData.getLimitTo()); |
| setIncludeMask(initialData.getIncludeMask()); |
| setMatchLocations(initialData.getMatchLocations()); |
| |
| fPattern.setText(initialData.getPattern()); |
| fIsCaseSensitive= initialData.isCaseSensitive(); |
| fJavaElement= initialData.getJavaElement(); |
| fCaseSensitive.setEnabled(fJavaElement == null); |
| fCaseSensitive.setSelection(initialData.isCaseSensitive()); |
| |
| |
| if (initialData.getWorkingSets() != null) |
| getContainer().setSelectedWorkingSets(initialData.getWorkingSets()); |
| else |
| getContainer().setSelectedScope(initialData.getScope()); |
| |
| fInitialData= initialData; |
| } |
| |
| |
| private Control createSearchFor(Composite parent) { |
| Group result= new Group(parent, SWT.NONE); |
| result.setText(SearchMessages.SearchPage_searchFor_label); |
| result.setLayout(new GridLayout(2, true)); |
| |
| fSearchFor= new Button[] { |
| createButton(result, SWT.RADIO, SearchMessages.SearchPage_searchFor_type, TYPE, true), |
| createButton(result, SWT.RADIO, SearchMessages.SearchPage_searchFor_method, METHOD, false), |
| createButton(result, SWT.RADIO, SearchMessages.SearchPage_searchFor_package, PACKAGE, false), |
| createButton(result, SWT.RADIO, SearchMessages.SearchPage_searchFor_constructor, CONSTRUCTOR, false), |
| createButton(result, SWT.RADIO, SearchMessages.SearchPage_searchFor_module, MODULE, false), |
| createButton(result, SWT.RADIO, SearchMessages.SearchPage_searchFor_field, FIELD, false) |
| }; |
| |
| return result; |
| } |
| |
| private Control createLimitTo(Composite parent) { |
| fLimitToGroup= new Group(parent, SWT.NONE); |
| fLimitToGroup.setText(SearchMessages.SearchPage_limitTo_label); |
| fLimitToGroup.setLayout(new GridLayout(2, false)); |
| |
| fillLimitToGroup(TYPE, ALL_OCCURRENCES); |
| |
| return fLimitToGroup; |
| } |
| |
| private void fillLimitToGroup(int searchFor, int limitTo) { |
| for (Control child : fLimitToGroup.getChildren()) { |
| child.dispose(); |
| } |
| fMatchLocationsLink= null; |
| |
| |
| ArrayList<Button> buttons= new ArrayList<>(); |
| buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_allOccurrences, ALL_OCCURRENCES, limitTo == ALL_OCCURRENCES)); |
| buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_declarations, DECLARATIONS, limitTo == DECLARATIONS)); |
| |
| buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_references, REFERENCES, limitTo == REFERENCES)); |
| if (searchFor == TYPE) { |
| buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_implementors, IMPLEMENTORS, limitTo == IMPLEMENTORS)); |
| |
| buttons.add(createMethodLocationRadio(limitTo == SPECIFIC_REFERENCES)); |
| } |
| |
| if (searchFor == FIELD) { |
| buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_readReferences, READ_ACCESSES, limitTo == READ_ACCESSES)); |
| buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_writeReferences, WRITE_ACCESSES, limitTo == WRITE_ACCESSES)); |
| |
| // buttons.add(createMethodLocationRadio(limitTo == SPECIFIC_REFERENCES)); |
| } |
| |
| if (searchFor == METHOD || searchFor == CONSTRUCTOR) { |
| buttons.add(createMethodLocationRadio(limitTo == SPECIFIC_REFERENCES)); |
| } |
| |
| fLimitTo= buttons.toArray(new Button[buttons.size()]); |
| |
| SelectionAdapter listener= new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| performLimitToSelectionChanged((Button) e.widget); |
| } |
| }; |
| for (Button b : fLimitTo) { |
| b.addSelectionListener(listener); |
| } |
| Dialog.applyDialogFont(fLimitToGroup); // re-apply font as we disposed the previous widgets |
| |
| fLimitToGroup.layout(); |
| // // searchFor == FIELD needs one more row than the others |
| // fLimitToGroup.getShell().layout(new Control[] { fLimitToGroup.getChildren()[0] }); |
| } |
| |
| |
| private Button createMethodLocationRadio(boolean isSelected) { |
| if (fLimitToGroup.getChildren().length % 2 != 0) |
| new Label(fLimitToGroup, SWT.NONE); |
| |
| Button button= createButton(fLimitToGroup, SWT.RADIO, SearchMessages.JavaSearchPage_match_locations_label, SPECIFIC_REFERENCES, isSelected); |
| fMatchLocationsLink= new Link(fLimitToGroup, SWT.NONE); |
| fMatchLocationsLink.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| fMatchLocationsLink.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetDefaultSelected(SelectionEvent e) { |
| performConfigureMatchLocation(); |
| } |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| performConfigureMatchLocation(); |
| } |
| }); |
| fMatchLocationsLink.getAccessible().addAccessibleListener(new AccessibleAdapter() { |
| /* |
| * @see org.eclipse.swt.accessibility.AccessibleAdapter#getName(org.eclipse.swt.accessibility.AccessibleEvent) |
| * @since 3.8 |
| */ |
| @Override |
| public void getName(AccessibleEvent e) { |
| if (e.childID == ACC.CHILDID_SELF) |
| e.result= SearchMessages.JavaSearchPage_match_location_link_label_tooltip; |
| } |
| }); |
| updateMatchLocationText(); |
| |
| return button; |
| } |
| |
| private void updateMatchLocationText() { |
| if (fMatchLocationsLink != null) { |
| int searchFor= getSearchFor(); |
| int totNum= MatchLocations.getTotalNumberOfSettings(searchFor); |
| int currNum= MatchLocations.getNumberOfSelectedSettings(fMatchLocations, searchFor); |
| |
| fMatchLocationsLink.setText(Messages.format(SearchMessages.JavaSearchPage_match_location_link_label, new Object[] { Integer.valueOf(currNum), Integer.valueOf(totNum) })); |
| fMatchLocationsLink.setToolTipText(SearchMessages.JavaSearchPage_match_location_link_label_tooltip); |
| } |
| } |
| |
| protected final void performLimitToSelectionChanged(Button button) { |
| if (button.getSelection()) { |
| for (Button curr : fLimitTo) { |
| if (curr != button) { |
| curr.setSelection(false); |
| } |
| } |
| } |
| updateUseJRE(); |
| } |
| |
| |
| protected final void performConfigureMatchLocation() { |
| for (Button curr : fLimitTo) { |
| curr.setSelection(getIntData(curr) == SPECIFIC_REFERENCES); |
| } |
| |
| MatchLocationSelectionDialog locationSelectionDialog= new MatchLocationSelectionDialog(getShell(), fMatchLocations, getSearchFor()); |
| if (locationSelectionDialog.open() == Window.OK) { |
| setMatchLocations(locationSelectionDialog.getCurrentSelection()); |
| } |
| } |
| |
| |
| private Control createIncludeMask(Composite parent) { |
| Group result= new Group(parent, SWT.NONE); |
| result.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); |
| result.setText(SearchMessages.SearchPage_searchIn_label); |
| result.setLayout(new GridLayout(4, false)); |
| fIncludeMasks= new Button[] { |
| createButton(result, SWT.CHECK, SearchMessages.SearchPage_searchIn_sources, JavaSearchScopeFactory.SOURCES, true), |
| createButton(result, SWT.CHECK, SearchMessages.SearchPage_searchIn_projects, JavaSearchScopeFactory.PROJECTS, true), |
| createButton(result, SWT.CHECK, SearchMessages.SearchPage_searchIn_jre, JavaSearchScopeFactory.JRE, false), |
| createButton(result, SWT.CHECK, SearchMessages.SearchPage_searchIn_libraries, JavaSearchScopeFactory.LIBS, true), |
| }; |
| |
| SelectionAdapter listener= new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| updateOKStatus(); |
| } |
| }; |
| for (Button fIncludeMask : fIncludeMasks) { |
| fIncludeMask.addSelectionListener(listener); |
| } |
| |
| return result; |
| } |
| |
| private Button createButton(Composite parent, int style, String text, int data, boolean isSelected) { |
| Button button= new Button(parent, style); |
| button.setText(text); |
| button.setData(Integer.valueOf(data)); |
| button.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); |
| button.setSelection(isSelected); |
| return button; |
| } |
| |
| private void initSelections() { |
| ISelection sel= getContainer().getSelection(); |
| |
| IWorkbenchPage activePage= JavaPlugin.getActivePage(); |
| if (activePage != null) { |
| IWorkbenchPart activePart= activePage.getActivePart(); |
| if (activePart instanceof JavaEditor) { |
| JavaEditor javaEditor= (JavaEditor) activePart; |
| if (javaEditor.isBreadcrumbActive()) { |
| sel= javaEditor.getBreadcrumb().getSelectionProvider().getSelection(); |
| } |
| } |
| } |
| |
| SearchPatternData initData= null; |
| |
| if (sel instanceof IStructuredSelection) { |
| initData= tryStructuredSelection((IStructuredSelection) sel); |
| } else if (sel instanceof ITextSelection) { |
| IEditorPart activeEditor= getActiveEditor(); |
| if (activeEditor instanceof JavaEditor) { |
| try { |
| IJavaElement[] elements= SelectionConverter.codeResolve((JavaEditor) activeEditor); |
| if (elements != null && elements.length > 0) { |
| initData= determineInitValuesFrom(elements[0]); |
| } |
| } catch (JavaModelException e) { |
| // ignore |
| } |
| } |
| if (initData == null) { |
| initData= trySimpleTextSelection((ITextSelection) sel); |
| } |
| } |
| if (initData == null) { |
| initData= getDefaultInitValues(); |
| } |
| |
| fInitialData= initData; |
| fJavaElement= initData.getJavaElement(); |
| fCaseSensitive.setSelection(initData.isCaseSensitive()); |
| fCaseSensitive.setEnabled(fJavaElement == null); |
| |
| setSearchFor(initData.getSearchFor()); |
| setLimitTo(initData.getSearchFor(), initData.getLimitTo()); |
| setIncludeMask(initData.getIncludeMask()); |
| setMatchLocations(initData.getMatchLocations()); |
| |
| fPattern.setText(initData.getPattern()); |
| } |
| |
| private void updateUseJRE() { |
| setIncludeMask(getIncludeMask()); |
| } |
| |
| private static boolean forceIncludeAll(int limitTo, IJavaElement elem) { |
| return elem != null && (limitTo == DECLARATIONS || limitTo == IMPLEMENTORS); |
| } |
| |
| private SearchPatternData tryStructuredSelection(IStructuredSelection selection) { |
| if (selection == null || selection.size() > 1) |
| return null; |
| |
| Object o= selection.getFirstElement(); |
| SearchPatternData res= null; |
| if (o instanceof IJavaElement) { |
| res= determineInitValuesFrom((IJavaElement) o); |
| } else if (o instanceof LogicalPackage) { |
| LogicalPackage lp= (LogicalPackage)o; |
| return new SearchPatternData(PACKAGE, REFERENCES, 0, fIsCaseSensitive, lp.getElementName(), null, getLastIncludeMask()); |
| } else if (o instanceof IAdaptable) { |
| IJavaElement element= ((IAdaptable) o).getAdapter(IJavaElement.class); |
| if (element != null) { |
| res= determineInitValuesFrom(element); |
| } |
| } |
| if (res == null && o instanceof IAdaptable) { |
| IWorkbenchAdapter adapter= ((IAdaptable)o).getAdapter(IWorkbenchAdapter.class); |
| if (adapter != null) { |
| return new SearchPatternData(TYPE, REFERENCES, 0, fIsCaseSensitive, adapter.getLabel(o), null, getLastIncludeMask()); |
| } |
| } |
| return res; |
| } |
| |
| final static boolean isSearchableType(IJavaElement element) { |
| switch (element.getElementType()) { |
| case IJavaElement.PACKAGE_FRAGMENT: |
| case IJavaElement.PACKAGE_DECLARATION: |
| case IJavaElement.IMPORT_DECLARATION: |
| case IJavaElement.TYPE: |
| case IJavaElement.FIELD: |
| case IJavaElement.METHOD: |
| case IJavaElement.JAVA_MODULE: |
| return true; |
| } |
| return false; |
| } |
| |
| private SearchPatternData determineInitValuesFrom(IJavaElement element) { |
| try { |
| //JavaSearchScopeFactory factory= JavaSearchScopeFactory.getInstance(); |
| //boolean isInsideJRE= factory.isInsideJRE(element); |
| int includeMask= getLastIncludeMask(); |
| |
| switch (element.getElementType()) { |
| case IJavaElement.JAVA_MODULE: |
| return new SearchPatternData(MODULE, REFERENCES, 0, true, element.getElementName(), element, includeMask); |
| case IJavaElement.PACKAGE_FRAGMENT: |
| case IJavaElement.PACKAGE_DECLARATION: |
| return new SearchPatternData(PACKAGE, REFERENCES, 0, true, element.getElementName(), element, includeMask); |
| case IJavaElement.IMPORT_DECLARATION: { |
| IImportDeclaration declaration= (IImportDeclaration) element; |
| if (declaration.isOnDemand()) { |
| String name= Signature.getQualifier(declaration.getElementName()); |
| return new SearchPatternData(PACKAGE, DECLARATIONS, 0, true, name, element, JavaSearchScopeFactory.ALL); |
| } |
| return new SearchPatternData(TYPE, DECLARATIONS, 0, true, element.getElementName(), element, JavaSearchScopeFactory.ALL); |
| } |
| case IJavaElement.TYPE: |
| return new SearchPatternData(TYPE, REFERENCES, 0, true, PatternStrings.getTypeSignature((IType) element), element, includeMask); |
| case IJavaElement.COMPILATION_UNIT: { |
| ICompilationUnit cu= (ICompilationUnit) element; |
| IType mainType= cu.findPrimaryType(); |
| if (mainType != null) { |
| return new SearchPatternData(TYPE, REFERENCES, 0, true, PatternStrings.getTypeSignature(mainType), mainType, includeMask); |
| } |
| IModuleDescription module= cu.getModule(); |
| if (module != null && module.exists()) { |
| return new SearchPatternData(MODULE, REFERENCES, 0, true, PatternStrings.getSignature(module), module, includeMask); |
| } |
| break; |
| } |
| case IJavaElement.CLASS_FILE: { |
| if (element instanceof IOrdinaryClassFile) { |
| IType mainType= ((IOrdinaryClassFile) element).getType(); |
| if (mainType.exists()) { |
| return new SearchPatternData(TYPE, REFERENCES, 0, true, PatternStrings.getTypeSignature(mainType), mainType, includeMask); |
| } |
| } else if (element instanceof IModularClassFile) { |
| IModuleDescription module= ((IModularClassFile) element).getModule(); |
| if (module != null && module.exists()) { |
| return new SearchPatternData(MODULE, REFERENCES, 0, true, PatternStrings.getSignature(module), module, includeMask); |
| } |
| |
| } |
| break; |
| } |
| case IJavaElement.FIELD: |
| return new SearchPatternData(FIELD, REFERENCES, 0, true, PatternStrings.getFieldSignature((IField) element), element, includeMask); |
| case IJavaElement.METHOD: |
| IMethod method= (IMethod) element; |
| int searchFor= method.isConstructor() ? CONSTRUCTOR : METHOD; |
| return new SearchPatternData(searchFor, REFERENCES, 0, true, PatternStrings.getMethodSignature(method), element, includeMask); |
| } |
| |
| } catch (JavaModelException e) { |
| if (!e.isDoesNotExist()) { |
| ExceptionHandler.handle(e, SearchMessages.Search_Error_javaElementAccess_title, SearchMessages.Search_Error_javaElementAccess_message); |
| } |
| // element might not exist |
| } |
| return null; |
| } |
| |
| private SearchPatternData trySimpleTextSelection(ITextSelection selection) { |
| String selectedText= selection.getText(); |
| if (selectedText != null && selectedText.length() > 0) { |
| int i= 0; |
| while (i < selectedText.length() && !IndentManipulation.isLineDelimiterChar(selectedText.charAt(i))) { |
| i++; |
| } |
| if (i > 0) { |
| return new SearchPatternData(TYPE, REFERENCES, 0, fIsCaseSensitive, selectedText.substring(0, i), null, JavaSearchScopeFactory.ALL); |
| } |
| } |
| return null; |
| } |
| |
| private SearchPatternData getDefaultInitValues() { |
| if (!fPreviousSearchPatterns.isEmpty()) { |
| return fPreviousSearchPatterns.get(0); |
| } |
| |
| return new SearchPatternData(TYPE, REFERENCES, 0, fIsCaseSensitive, "", null, getLastIncludeMask()); //$NON-NLS-1$ |
| } |
| |
| private int getLastIncludeMask() { |
| try { |
| return getDialogSettings().getInt(STORE_INCLUDE_MASK); |
| } catch (NumberFormatException e) { |
| return JavaSearchScopeFactory.NO_JRE; |
| } |
| } |
| |
| /* |
| * Implements method from ISearchPage |
| */ |
| @Override |
| public void setContainer(ISearchPageContainer container) { |
| fContainer= container; |
| } |
| |
| /** |
| * Returns the search page's container. |
| * @return the search page container |
| */ |
| private ISearchPageContainer getContainer() { |
| return fContainer; |
| } |
| |
| private IEditorPart getActiveEditor() { |
| IWorkbenchPage activePage= JavaPlugin.getActivePage(); |
| if (activePage != null) { |
| return activePage.getActiveEditor(); |
| } |
| return null; |
| } |
| |
| //--------------- Configuration handling -------------- |
| |
| /** |
| * Returns the page settings for this Java search page. |
| * |
| * @return the page settings to be used |
| */ |
| private IDialogSettings getDialogSettings() { |
| if (fDialogSettings == null) { |
| fDialogSettings= JavaPlugin.getDefault().getDialogSettingsSection(PAGE_NAME); |
| } |
| return fDialogSettings; |
| } |
| |
| /** |
| * Initializes itself from the stored page settings. |
| */ |
| private void readConfiguration() { |
| IDialogSettings s= getDialogSettings(); |
| fIsCaseSensitive= s.getBoolean(STORE_CASE_SENSITIVE); |
| |
| try { |
| int historySize= s.getInt(STORE_HISTORY_SIZE); |
| for (int i= 0; i < historySize; i++) { |
| IDialogSettings histSettings= s.getSection(STORE_HISTORY + i); |
| if (histSettings != null) { |
| SearchPatternData data= SearchPatternData.create(histSettings); |
| if (data != null) { |
| fPreviousSearchPatterns.add(data); |
| } |
| } |
| } |
| } catch (NumberFormatException e) { |
| // ignore |
| } |
| } |
| |
| /** |
| * Stores the current configuration in the dialog store. |
| */ |
| private void writeConfiguration() { |
| IDialogSettings s= getDialogSettings(); |
| s.put(STORE_CASE_SENSITIVE, fIsCaseSensitive); |
| s.put(STORE_INCLUDE_MASK, getIncludeMask()); |
| |
| int historySize= Math.min(fPreviousSearchPatterns.size(), HISTORY_SIZE); |
| s.put(STORE_HISTORY_SIZE, historySize); |
| for (int i= 0; i < historySize; i++) { |
| IDialogSettings histSettings= s.addNewSection(STORE_HISTORY + i); |
| SearchPatternData data= fPreviousSearchPatterns.get(i); |
| data.store(histSettings); |
| } |
| } |
| } |