diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java | 465 |
1 files changed, 0 insertions, 465 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java deleted file mode 100644 index b1b5390ee..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt; - -import static com.android.SdkConstants.CLASS_CONSTRUCTOR; -import static com.android.SdkConstants.CONSTRUCTOR_NAME; - -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; -import com.android.ide.eclipse.adt.internal.project.ProjectHelper; -import com.android.ide.eclipse.ddms.ISourceRevealer; -import com.google.common.base.Predicate; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IMethod; -import org.eclipse.jdt.core.ISourceRange; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.core.search.IJavaSearchConstants; -import org.eclipse.jdt.core.search.SearchEngine; -import org.eclipse.jdt.core.search.SearchMatch; -import org.eclipse.jdt.core.search.SearchParticipant; -import org.eclipse.jdt.core.search.SearchPattern; -import org.eclipse.jdt.core.search.SearchRequestor; -import org.eclipse.jdt.ui.JavaUI; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.window.Window; -import org.eclipse.ui.IPerspectiveRegistry; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.WorkbenchException; -import org.eclipse.ui.dialogs.ListDialog; -import org.eclipse.ui.ide.IDE; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Implementation of the com.android.ide.ddms.sourceRevealer extension point. - * Note that this code is duplicated in the PDT plugin's SourceRevealer as well. - */ -public class SourceRevealer implements ISourceRevealer { - @Override - public boolean reveal(String applicationName, String className, int line) { - IProject project = ProjectHelper.findAndroidProjectByAppName(applicationName); - if (project != null) { - return BaseProjectHelper.revealSource(project, className, line); - } - - return false; - } - - /** - * Reveal the source for given fully qualified method name.<br> - * - * The method should take care of the following scenarios:<ol> - * <li> A search, either by filename/line number, or for fqmn might provide only 1 result. - * In such a case, just open that result. Give preference to the file name/line # search - * since that is the most accurate (gets to the line number). </li> - * <li> The search might not provide any results. e.g, the method name may be of the form - * "com.x.y$1.methodName". Searches for methods within anonymous classes will fail. In - * such a case, if the fileName:lineNumber argument is available, a search for that - * should be made instead. </li> - * <li> The search might provide multiple results. In such a case, the fileName/lineNumber - * values should be utilized to narrow down the results.</li> - * </ol> - * - * @param fqmn fully qualified method name - * @param fileName file name in which the method is present, null if not known - * @param lineNumber line number in the file which should be given focus, -1 if not known. - * Line numbers begin at 1, not 0. - * @param perspective perspective to switch to before the source is revealed, null to not - * switch perspectives - */ - @Override - public boolean revealMethod(String fqmn, String fileName, int lineNumber, String perspective) { - // Search by filename:linenumber. If there is just one result for it, that would - // be the correct match that is accurate to the line - List<SearchMatch> fileMatches = Collections.emptyList(); - if (fileName != null && lineNumber >= 0) { - fileMatches = searchForFile(fileName); - if (fileMatches.size() == 1) { - return revealLineMatch(fileMatches, fileName, lineNumber, perspective); - } - } - - List<SearchMatch> methodMatches = searchForMethod(fqmn); - - // if there is a unique method name match: - // 1. if there are > 1 file name matches, try to see if they can be narrowed down - // 2. if not, display the method match - if (methodMatches.size() == 1) { - if (fileMatches.size() > 0) { - List<SearchMatch> filteredMatches = filterMatchByResource(fileMatches, - methodMatches.get(0).getResource()); - if (filteredMatches.size() == 1) { - return revealLineMatch(filteredMatches, fileName, lineNumber, perspective); - } - } else if (fileName != null && lineNumber > 0) { - // Couldn't find file match, but we have a filename and line number: attempt - // to use this to pinpoint the location within the method - IMethod method = (IMethod) methodMatches.get(0).getElement(); - IJavaElement element = method; - while (element != null) { - if (element instanceof ICompilationUnit) { - ICompilationUnit unit = ((ICompilationUnit) element).getPrimary(); - IResource resource = unit.getResource(); - if (resource instanceof IFile) { - IFile file = (IFile) resource; - - try { - // See if the line number looks like it's inside the given method - ISourceRange sourceRange = method.getSourceRange(); - IRegion region = AdtUtils.getRegionOfLine(file, lineNumber - 1); - // When fields are initialized with code, this logically belongs - // to the constructor, but the line numbers are outside of the - // constructor. In this case we'll trust the line number rather - // than the method range. - boolean isConstructor = fqmn.endsWith(CONSTRUCTOR_NAME); - if (isConstructor - || region != null - && region.getOffset() >= sourceRange.getOffset() - && region.getOffset() < sourceRange.getOffset() - + sourceRange.getLength()) { - // Yes: use the line number instead - if (perspective != null) { - SourceRevealer.switchToPerspective(perspective); - } - return displayFile(file, lineNumber); - } - - } catch (JavaModelException e) { - AdtPlugin.log(e, null); - } - } - } - element = element.getParent(); - } - - } - - return displayMethod((IMethod) methodMatches.get(0).getElement(), perspective); - } - - // no matches for search by method, so search by filename - if (methodMatches.size() == 0) { - if (fileMatches.size() > 0) { - return revealLineMatch(fileMatches, fileName, lineNumber, perspective); - } else { - // Last ditch effort: attempt to look up the class corresponding to the fqn - // and jump to the line there - if (fileMatches.isEmpty() && fqmn.indexOf('.') != -1) { - String className = fqmn.substring(0, fqmn.lastIndexOf('.')); - for (IJavaProject project : BaseProjectHelper.getAndroidProjects(null)) { - IType type; - try { - type = project.findType(className); - if (type != null && type.exists()) { - IResource resource = type.getResource(); - if (resource instanceof IFile) { - if (perspective != null) { - SourceRevealer.switchToPerspective(perspective); - } - return displayFile((IFile) resource, lineNumber); - } - } - } catch (JavaModelException e) { - AdtPlugin.log(e, null); - } - } - } - - return false; - } - } - - // multiple matches for search by method, narrow down by filename - if (fileName != null) { - return revealLineMatch( - filterMatchByFileName(methodMatches, fileName), - fileName, lineNumber, perspective); - } - - // prompt the user - SearchMatch match = getMatchToDisplay(methodMatches, fqmn); - if (match == null) { - return false; - } else { - return displayMethod((IMethod) match.getElement(), perspective); - } - } - - private boolean revealLineMatch(List<SearchMatch> matches, String fileName, int lineNumber, - String perspective) { - SearchMatch match = getMatchToDisplay(matches, - String.format("%s:%d", fileName, lineNumber)); - if (match == null) { - return false; - } - - if (perspective != null) { - SourceRevealer.switchToPerspective(perspective); - } - - return displayFile((IFile) match.getResource(), lineNumber); - } - - private boolean displayFile(IFile file, int lineNumber) { - try { - IMarker marker = file.createMarker(IMarker.TEXT); - marker.setAttribute(IMarker.LINE_NUMBER, lineNumber); - IDE.openEditor( - PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), - marker); - marker.delete(); - return true; - } catch (CoreException e) { - AdtPlugin.printErrorToConsole(e.getMessage()); - return false; - } - } - - private boolean displayMethod(IMethod method, String perspective) { - if (perspective != null) { - SourceRevealer.switchToPerspective(perspective); - } - - try { - JavaUI.openInEditor(method); - return true; - } catch (Exception e) { - AdtPlugin.printErrorToConsole(e.getMessage()); - return false; - } - } - - private List<SearchMatch> filterMatchByFileName(List<SearchMatch> matches, String fileName) { - if (fileName == null) { - return matches; - } - - // Use a map to collapse multiple matches in a single file into just one match since - // we know the line number in the file. - Map<IResource, SearchMatch> matchesPerFile = - new HashMap<IResource, SearchMatch>(matches.size()); - - for (SearchMatch m: matches) { - if (m.getResource() instanceof IFile - && m.getResource().getName().startsWith(fileName)) { - matchesPerFile.put(m.getResource(), m); - } - } - - List<SearchMatch> filteredMatches = new ArrayList<SearchMatch>(matchesPerFile.values()); - - // sort results, first by project name, then by file name - Collections.sort(filteredMatches, new Comparator<SearchMatch>() { - @Override - public int compare(SearchMatch m1, SearchMatch m2) { - String p1 = m1.getResource().getProject().getName(); - String p2 = m2.getResource().getProject().getName(); - - if (!p1.equals(p2)) { - return p1.compareTo(p2); - } - - String r1 = m1.getResource().getName(); - String r2 = m2.getResource().getName(); - return r1.compareTo(r2); - } - }); - return filteredMatches; - } - - private List<SearchMatch> filterMatchByResource(List<SearchMatch> matches, - IResource resource) { - List<SearchMatch> filteredMatches = new ArrayList<SearchMatch>(matches.size()); - - for (SearchMatch m: matches) { - if (m.getResource().equals(resource)) { - filteredMatches.add(m); - } - } - - return filteredMatches; - } - - private SearchMatch getMatchToDisplay(List<SearchMatch> matches, String searchTerm) { - // no matches for given search - if (matches.size() == 0) { - return null; - } - - // there is only 1 match, so we return that - if (matches.size() == 1) { - return matches.get(0); - } - - // multiple matches, prompt the user to select - IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - if (window == null) { - return null; - } - - ListDialog dlg = new ListDialog(window.getShell()); - dlg.setMessage("Multiple files match search: " + searchTerm); - dlg.setTitle("Select file to open"); - dlg.setInput(matches); - dlg.setContentProvider(new IStructuredContentProvider() { - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - @Override - public void dispose() { - } - - @Override - public Object[] getElements(Object inputElement) { - return ((List<?>) inputElement).toArray(); - } - }); - dlg.setLabelProvider(new LabelProvider() { - @Override - public String getText(Object element) { - SearchMatch m = (SearchMatch) element; - return String.format("/%s/%s", //$NON-NLS-1$ - m.getResource().getProject().getName(), - m.getResource().getProjectRelativePath().toString()); - } - }); - dlg.setInitialSelections(new Object[] { matches.get(0) }); - dlg.setHelpAvailable(false); - - if (dlg.open() == Window.OK) { - Object[] selectedMatches = dlg.getResult(); - if (selectedMatches.length > 0) { - return (SearchMatch) selectedMatches[0]; - } - } - - return null; - } - - private List<SearchMatch> searchForFile(String fileName) { - return searchForPattern(fileName, IJavaSearchConstants.CLASS, MATCH_IS_FILE_PREDICATE); - } - - private List<SearchMatch> searchForMethod(String fqmn) { - if (fqmn.endsWith(CONSTRUCTOR_NAME)) { - fqmn = fqmn.substring(0, fqmn.length() - CONSTRUCTOR_NAME.length() - 1); // -1: dot - return searchForPattern(fqmn, IJavaSearchConstants.CONSTRUCTOR, - MATCH_IS_METHOD_PREDICATE); - } - if (fqmn.endsWith(CLASS_CONSTRUCTOR)) { - // Don't try to search for class init methods: Eclipse will throw NPEs if you do - return Collections.emptyList(); - } - - return searchForPattern(fqmn, IJavaSearchConstants.METHOD, MATCH_IS_METHOD_PREDICATE); - } - - private List<SearchMatch> searchForPattern(String pattern, int searchFor, - Predicate<SearchMatch> filterPredicate) { - SearchEngine se = new SearchEngine(); - SearchPattern searchPattern = SearchPattern.createPattern( - pattern, - searchFor, - IJavaSearchConstants.DECLARATIONS, - SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); - SearchResultAccumulator requestor = new SearchResultAccumulator(filterPredicate); - try { - se.search(searchPattern, - new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, - SearchEngine.createWorkspaceScope(), - requestor, - new NullProgressMonitor()); - } catch (CoreException e) { - AdtPlugin.printErrorToConsole(e.getMessage()); - return Collections.emptyList(); - } - - return requestor.getMatches(); - } - - private static final Predicate<SearchMatch> MATCH_IS_FILE_PREDICATE = - new Predicate<SearchMatch>() { - @Override - public boolean apply(SearchMatch match) { - return match.getResource() instanceof IFile; - } - }; - - private static final Predicate<SearchMatch> MATCH_IS_METHOD_PREDICATE = - new Predicate<SearchMatch>() { - @Override - public boolean apply(SearchMatch match) { - return match.getResource() instanceof IFile; - } - }; - - private static class SearchResultAccumulator extends SearchRequestor { - private final List<SearchMatch> mSearchMatches = new ArrayList<SearchMatch>(); - private final Predicate<SearchMatch> mPredicate; - - public SearchResultAccumulator(Predicate<SearchMatch> filterPredicate) { - mPredicate = filterPredicate; - } - - public List<SearchMatch> getMatches() { - return mSearchMatches; - } - - @Override - public void acceptSearchMatch(SearchMatch match) throws CoreException { - if (mPredicate.apply(match)) { - mSearchMatches.add(match); - } - } - } - - private static void switchToPerspective(String perspectiveId) { - IWorkbench workbench = PlatformUI.getWorkbench(); - IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); - IPerspectiveRegistry perspectiveRegistry = workbench.getPerspectiveRegistry(); - if (perspectiveId != null - && perspectiveId.length() > 0 - && perspectiveRegistry.findPerspectiveWithId(perspectiveId) != null) { - try { - workbench.showPerspective(perspectiveId, window); - } catch (WorkbenchException e) { - AdtPlugin.printErrorToConsole(e.getMessage()); - } - } - } -} |