| /******************************************************************************* |
| * Copyright (c) 2000, 2019 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: |
| * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation |
| * (report 36180: Callers/Callees view) |
| * Stephan Herrmann (stephan@cs.tu-berlin.de): |
| * - bug 206949: [call hierarchy] filter field accesses (only write or only read) |
| * Red Hat Inc - refactored to jdt.core.manipulatio |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.corext.callhierarchy; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.SubMonitor; |
| |
| import org.eclipse.jdt.core.Flags; |
| import org.eclipse.jdt.core.IField; |
| import org.eclipse.jdt.core.IInitializer; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IMember; |
| 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.IJavaSearchScope; |
| import org.eclipse.jdt.core.search.SearchEngine; |
| import org.eclipse.jdt.core.search.SearchParticipant; |
| import org.eclipse.jdt.core.search.SearchPattern; |
| |
| import org.eclipse.jdt.internal.core.manipulation.JavaManipulationPlugin; |
| import org.eclipse.jdt.internal.corext.util.JdtFlags; |
| import org.eclipse.jdt.internal.corext.util.SearchUtils; |
| |
| public class CallerMethodWrapper extends MethodWrapper { |
| /** |
| * Value of the expand with constructors mode. |
| * |
| * @since 3.5 |
| */ |
| private boolean fExpandWithConstructors; |
| |
| /** |
| * Tells whether the expand with constructors mode has been set. |
| * |
| * @see #setExpandWithConstructors(boolean) |
| * @since 3.5 |
| */ |
| private boolean fIsExpandWithConstructorsSet; |
| |
| public CallerMethodWrapper(MethodWrapper parent, MethodCall methodCall) { |
| super(parent, methodCall); |
| } |
| |
| protected IJavaSearchScope getSearchScope() { |
| return CallHierarchyCore.getDefault().getSearchScope(); |
| } |
| |
| @Override |
| protected String getTaskName() { |
| return CallHierarchyMessages.CallerMethodWrapper_taskname; |
| } |
| |
| @Override |
| public MethodWrapper createMethodWrapper(MethodCall methodCall) { |
| return new CallerMethodWrapper(this, methodCall); |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper#canHaveChildren() |
| */ |
| @Override |
| public boolean canHaveChildren() { |
| IMember member= getMember(); |
| if (member instanceof IField) { |
| if (getLevel() == 1) |
| return true; |
| int mode= getFieldSearchMode(); |
| return mode == IJavaSearchConstants.REFERENCES || mode == IJavaSearchConstants.READ_ACCESSES; |
| } |
| return member instanceof IMethod || member instanceof IType; |
| } |
| |
| /** |
| * @return The result of the search for children |
| * @see org.eclipse.jdt.internal.ui.callhierarchy.MethodWrapper#findChildren(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| @Override |
| protected Map<String, MethodCall> findChildren(IProgressMonitor progressMonitor) { |
| try { |
| |
| SubMonitor monitor = SubMonitor.convert(progressMonitor,"" , 95); //$NON-NLS-1$ |
| |
| checkCanceled(progressMonitor); |
| |
| IMember member= getMember(); |
| SearchPattern pattern= null; |
| IType type= null; |
| if (member instanceof IType) { |
| type= (IType) member; |
| } else if (member instanceof IInitializer && ! Flags.isStatic(member.getFlags())) { |
| type= (IType) member.getParent(); |
| } |
| if (type != null) { |
| if (type.isAnonymous()) { |
| // search engine does not find reference to anonymous, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=207774 |
| CallSearchResultCollector resultCollector= new CallSearchResultCollector(); |
| IJavaElement parent= type.getParent(); |
| if (parent instanceof IMember) { |
| IMember parentMember= (IMember) parent; |
| ISourceRange nameRange= type.getNameRange(); |
| int start= nameRange != null ? nameRange.getOffset() : -1; |
| int len= nameRange != null ? nameRange.getLength() : 0; |
| resultCollector.addMember(type, parentMember, start, start + len); |
| return resultCollector.getCallers(); |
| } |
| } else if (type.getParent() instanceof IMethod) { |
| // good enough for local types (does not find super(..) references in subtype constructors): |
| pattern= SearchPattern.createPattern(type, |
| IJavaSearchConstants.CLASS_INSTANCE_CREATION_TYPE_REFERENCE, |
| SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE); |
| } else { |
| pattern= SearchPattern.createPattern(type.getFullyQualifiedName('.'), |
| IJavaSearchConstants.CONSTRUCTOR, |
| IJavaSearchConstants.REFERENCES, |
| SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE); |
| } |
| } |
| if (pattern == null) { |
| int limitTo= IJavaSearchConstants.REFERENCES; |
| if (member.getElementType() == IJavaElement.FIELD) |
| limitTo= getFieldSearchMode(); |
| pattern= SearchPattern.createPattern(member, limitTo, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE); |
| } |
| if (pattern == null) { // e.g. for initializers |
| return new HashMap<>(0); |
| } |
| |
| SearchEngine searchEngine= new SearchEngine(); |
| MethodReferencesSearchRequestor searchRequestor= new MethodReferencesSearchRequestor(); |
| IJavaSearchScope defaultSearchScope= getSearchScope(); |
| boolean isWorkspaceScope= SearchEngine.createWorkspaceScope().equals(defaultSearchScope); |
| IJavaSearchScope searchScope= isWorkspaceScope ? getAccurateSearchScope(defaultSearchScope, member) : defaultSearchScope; |
| searchEngine.search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, searchScope, searchRequestor, |
| monitor); |
| return searchRequestor.getCallers(); |
| |
| } catch (CoreException e) { |
| JavaManipulationPlugin.log(e); |
| return new HashMap<>(0); |
| } |
| } |
| |
| private IJavaSearchScope getAccurateSearchScope(IJavaSearchScope defaultSearchScope, IMember member) throws JavaModelException { |
| if (! JdtFlags.isPrivate(member)) |
| return defaultSearchScope; |
| |
| if (member.getCompilationUnit() != null) { |
| return SearchEngine.createJavaSearchScope(new IJavaElement[] { member.getCompilationUnit() }); |
| } else if (member.getClassFile() != null) { |
| // member could be called from an inner class-> search |
| // package fragment (see also bug 109053): |
| return SearchEngine.createJavaSearchScope(new IJavaElement[] { member.getAncestor(IJavaElement.PACKAGE_FRAGMENT) }); |
| } else { |
| return defaultSearchScope; |
| } |
| } |
| |
| /** |
| * Returns the value of expand with constructors mode. |
| * |
| * @return <code>true</code> if in expand with constructors mode, <code>false</code> otherwise or if not yet set |
| * @see #isExpandWithConstructorsSet() |
| * |
| * @since 3.5 |
| */ |
| public boolean getExpandWithConstructors() { |
| return fIsExpandWithConstructorsSet && fExpandWithConstructors; |
| } |
| |
| /** |
| * Sets the expand with constructors mode. |
| * |
| * @param value <code>true</code> if in expand with constructors mode, <code>false</code> |
| * otherwise |
| * @since 3.5 |
| */ |
| public void setExpandWithConstructors(boolean value) { |
| fExpandWithConstructors= value; |
| fIsExpandWithConstructorsSet= true; |
| |
| } |
| |
| /** |
| * Tells whether the expand with constructors mode has been set. |
| * |
| * @return <code>true</code> if expand with constructors mode has been set explicitly, <code>false</code> otherwise |
| * @see #setExpandWithConstructors(boolean) |
| * @since 3.5 |
| */ |
| public boolean isExpandWithConstructorsSet() { |
| return fIsExpandWithConstructorsSet; |
| } |
| |
| } |