From 70ac5fdf6a666287e29d88eaf5ac0ec055fd6430 Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Fri, 13 Dec 2019 23:05:37 +0800 Subject: [PATCH] GH-508: Adopt the new call hierarchy LSP Signed-off-by: Jinbo Wang --- .../contentassist/SignatureHelpRequestor.java | 5 +- .../corext/callhierarchy/CallHierarchy.java | 267 ------------- .../callhierarchy/CallHierarchyMessages.java | 29 -- .../CallHierarchyMessages.properties | 13 - .../callhierarchy/CallHierarchyVisitor.java | 24 -- .../corext/callhierarchy/CallLocation.java | 134 ------- .../CallSearchResultCollector.java | 81 ---- .../callhierarchy/CalleeAnalyzerVisitor.java | 351 ----------------- .../callhierarchy/CalleeMethodWrapper.java | 102 ----- .../callhierarchy/CallerMethodWrapper.java | 213 ---------- .../callhierarchy/IImplementorFinder.java | 31 -- .../corext/callhierarchy/Implementors.java | 194 ---------- .../callhierarchy/JavaImplementorFinder.java | 60 --- .../corext/callhierarchy/MethodCall.java | 74 ---- .../MethodReferencesSearchRequestor.java | 55 --- .../corext/callhierarchy/MethodWrapper.java | 363 ------------------ .../corext/callhierarchy/RealCallers.java | 39 -- .../handlers/CallHierarchyHandler.java | 249 +++++++----- .../handlers/CallHierarchyResolveHandler.java | 47 --- .../handlers/CompletionResolveHandler.java | 5 +- .../core/internal/handlers/InitHandler.java | 4 +- .../internal/handlers/JDTLanguageServer.java | 33 +- .../preferences/ClientPreferences.java | 2 +- .../org.eclipse.jdt.ls.tp.target | 8 +- .../handlers/CallHierarchyHandlerTest.java | 194 +++++----- .../CallHierarchyResolveHandlerTest.java | 78 ---- 26 files changed, 291 insertions(+), 2364 deletions(-) delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchy.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyMessages.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyMessages.properties delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyVisitor.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallLocation.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallSearchResultCollector.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CalleeAnalyzerVisitor.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CalleeMethodWrapper.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallerMethodWrapper.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/IImplementorFinder.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/Implementors.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/JavaImplementorFinder.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodCall.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodReferencesSearchRequestor.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodWrapper.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/RealCallers.java delete mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyResolveHandler.java delete mode 100644 org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyResolveHandlerTest.java diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SignatureHelpRequestor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SignatureHelpRequestor.java index 6978516c3d..48e6448af3 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SignatureHelpRequestor.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/contentassist/SignatureHelpRequestor.java @@ -22,6 +22,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.eclipse.core.runtime.IProgressMonitor; @@ -190,10 +191,10 @@ public String computeJavaDoc(CompletionProposal proposal) { String javadoc = null; try { - javadoc = new SimpleTimeLimiter().callWithTimeout(() -> { + javadoc = SimpleTimeLimiter.create(Executors.newCachedThreadPool()).callWithTimeout(() -> { Reader reader = JavadocContentAccess.getPlainTextContentReader(method); return reader == null? null:CharStreams.toString(reader); - }, 500, TimeUnit.MILLISECONDS, true); + }, 500, TimeUnit.MILLISECONDS); } catch (UncheckedTimeoutException tooSlow) { } catch (Exception e) { JavaLanguageServerPlugin.logException("Unable to read documentation", e); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchy.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchy.java deleted file mode 100644 index 6889c53c99..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchy.java +++ /dev/null @@ -1,267 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * 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 75800: [call hierarchy] should allow searches for fields - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.StringTokenizer; - -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IMember; -import org.eclipse.jdt.core.IMethod; -import org.eclipse.jdt.core.IModuleDescription; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.ITypeRoot; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.core.dom.ASTParser; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.search.IJavaSearchScope; -import org.eclipse.jdt.core.search.SearchEngine; -import org.eclipse.jdt.internal.corext.dom.IASTSharedValues; -import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil; -import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; -import org.eclipse.jdt.ls.core.internal.contentassist.StringMatcher; - -public class CallHierarchy { - private static final String PREF_USE_IMPLEMENTORS= "PREF_USE_IMPLEMENTORS"; //$NON-NLS-1$ - private static final String PREF_USE_FILTERS = "PREF_USE_FILTERS"; //$NON-NLS-1$ - private static final String PREF_FILTERS_LIST = "PREF_FILTERS_LIST"; //$NON-NLS-1$ - - private static final String DEFAULT_IGNORE_FILTERS = ""; //$NON-NLS-1$ - private static CallHierarchy fgInstance; - private IJavaSearchScope fSearchScope; - private StringMatcher[] fFilters; - - public static CallHierarchy getDefault() { - if (fgInstance == null) { - fgInstance = new CallHierarchy(); - } - - return fgInstance; - } - - public boolean isSearchUsingImplementorsEnabled() { - return true; - } - - public Collection getImplementingMethods(IMethod method) { - if (isSearchUsingImplementorsEnabled()) { - IJavaElement[] result = Implementors.getInstance().searchForImplementors(new IJavaElement[] { - method - }, new NullProgressMonitor()); - - if ((result != null) && (result.length > 0)) { - return Arrays.asList(result); - } - } - - return new ArrayList<>(0); - } - - public Collection getInterfaceMethods(IMethod method) { - if (isSearchUsingImplementorsEnabled()) { - IJavaElement[] result = Implementors.getInstance().searchForInterfaces(new IJavaElement[] { - method - }, new NullProgressMonitor()); - - if ((result != null) && (result.length > 0)) { - return Arrays.asList(result); - } - } - - return new ArrayList<>(0); - } - - public MethodWrapper[] getCallerRoots(IMember[] members) { - return getRoots(members, true); - } - - public MethodWrapper[] getCalleeRoots(IMember[] members) { - return getRoots(members, false); - } - - private MethodWrapper[] getRoots(IMember[] members, boolean callers) { - ArrayList roots= new ArrayList<>(); - for (int i= 0; i < members.length; i++) { - IMember member= members[i]; - if (member instanceof IType) { - IType type= (IType) member; - try { - if (! type.isAnonymous()) { - IMethod[] constructors= JavaElementUtil.getAllConstructors(type); - if (constructors.length == 0) { - addRoot(member, roots, callers); // IType is a stand-in for the non-existing default constructor - } else { - for (int j= 0; j < constructors.length; j++) { - IMethod constructor= constructors[j]; - addRoot(constructor, roots, callers); - } - } - } else { - addRoot(member, roots, callers); - } - } catch (JavaModelException e) { - JavaLanguageServerPlugin.log(e); - } - } else { - addRoot(member, roots, callers); - } - } - return roots.toArray(new MethodWrapper[roots.size()]); - } - - private void addRoot(IMember member, ArrayList roots, boolean callers) { - MethodCall methodCall= new MethodCall(member); - MethodWrapper root; - if (callers) { - root= new CallerMethodWrapper(null, methodCall); - } else { - root= new CalleeMethodWrapper(null, methodCall); - } - roots.add(root); - } - - public static CallLocation getCallLocation(Object element) { - CallLocation callLocation = null; - - if (element instanceof MethodWrapper) { - MethodWrapper methodWrapper = (MethodWrapper) element; - MethodCall methodCall = methodWrapper.getMethodCall(); - - if (methodCall != null) { - callLocation = methodCall.getFirstCallLocation(); - } - } else if (element instanceof CallLocation) { - callLocation = (CallLocation) element; - } - - return callLocation; - } - - public IJavaSearchScope getSearchScope() { - if (fSearchScope == null) { - fSearchScope= SearchEngine.createWorkspaceScope(); - } - - return fSearchScope; - } - - public void setSearchScope(IJavaSearchScope searchScope) { - this.fSearchScope = searchScope; - } - - /** - * Checks whether the fully qualified name is ignored by the set filters. - * - * @param fullyQualifiedName the fully qualified name - * - * @return true if the fully qualified name is ignored - */ - public boolean isIgnored(String fullyQualifiedName) { - if ((getIgnoreFilters() != null) && (getIgnoreFilters().length > 0)) { - for (int i = 0; i < getIgnoreFilters().length; i++) { - String fullyQualifiedName1 = fullyQualifiedName; - - if (getIgnoreFilters()[i].match(fullyQualifiedName1)) { - return true; - } - } - } - - return false; - } - - /** - * Returns filters for packages which should not be included in the search results. - * - * @return StringMatcher[] - */ - private StringMatcher[] getIgnoreFilters() { - if (fFilters == null) { - fFilters = parseList(DEFAULT_IGNORE_FILTERS); - } - - return fFilters; - } - - public static boolean arePossibleInputElements(List elements) { - if (elements.size() < 1) { - return false; - } - for (Iterator iter= elements.iterator(); iter.hasNext();) { - if (! isPossibleInputElement(iter.next())) { - return false; - } - } - return true; - } - - /** - * Parses the comma separated string into an array of {@link StringMatcher} objects. - * - * @param listString the string to parse - * @return an array of {@link StringMatcher} objects - */ - private static StringMatcher[] parseList(String listString) { - List list = new ArrayList<>(10); - StringTokenizer tokenizer = new StringTokenizer(listString, ","); //$NON-NLS-1$ - - while (tokenizer.hasMoreTokens()) { - String textFilter = tokenizer.nextToken().trim(); - list.add(new StringMatcher(textFilter, false, false)); - } - - return list.toArray(new StringMatcher[list.size()]); - } - - static CompilationUnit getCompilationUnitNode(IMember member, boolean resolveBindings) { - ITypeRoot typeRoot= member.getTypeRoot(); - try { - if (typeRoot.exists() && typeRoot.getBuffer() != null) { - ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); - parser.setSource(typeRoot); - parser.setResolveBindings(resolveBindings); - return (CompilationUnit) parser.createAST(null); - } - } catch (JavaModelException e) { - JavaLanguageServerPlugin.logException(e); - } - return null; - } - - public static boolean isPossibleInputElement(Object element){ - if (! (element instanceof IMember)) { - return false; - } - - if (element instanceof IModuleDescription) { - return false; - } - - if (element instanceof IType) { - IType type= (IType) element; - try { - return type.isClass() || type.isEnum(); - } catch (JavaModelException e) { - return false; - } - } - - return true; - } -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyMessages.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyMessages.java deleted file mode 100644 index 754018deed..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyMessages.java +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import org.eclipse.osgi.util.NLS; - -public final class CallHierarchyMessages extends NLS { - - private static final String BUNDLE_NAME= "org.eclipse.jdt.internal.corext.callhierarchy.CallHierarchyMessages";//$NON-NLS-1$ - - private CallHierarchyMessages() { - // Do not instantiate - } - - public static String CallerMethodWrapper_taskname; - public static String CalleeMethodWrapper_taskname; - - static { - NLS.initializeMessages(BUNDLE_NAME, CallHierarchyMessages.class); - } -} \ No newline at end of file diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyMessages.properties b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyMessages.properties deleted file mode 100644 index adfd8c3efe..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyMessages.properties +++ /dev/null @@ -1,13 +0,0 @@ -############################################################################### -# Copyright (c) 2000, 2005 IBM Corporation and others. -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -# -# Contributors: -# Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation -# (report 36180: Callers/Callees view) -############################################################################### -CallerMethodWrapper_taskname=Finding callers... -CalleeMethodWrapper_taskname=Finding callees... diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyVisitor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyVisitor.java deleted file mode 100644 index c5d561ae95..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallHierarchyVisitor.java +++ /dev/null @@ -1,24 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation - * (report 36180: Callers/Callees view) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -public abstract class CallHierarchyVisitor { - public void preVisit(MethodWrapper methodWrapper) { - } - - public void postVisit(MethodWrapper methodWrapper) { - } - - public boolean visit(MethodWrapper methodWrapper) { - return true; - } -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallLocation.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallLocation.java deleted file mode 100644 index b2c55e08ea..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallLocation.java +++ /dev/null @@ -1,134 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation - * (report 36180: Callers/Callees view) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.jdt.core.IBuffer; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IMember; -import org.eclipse.jdt.core.IOpenable; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.Document; - -public class CallLocation implements IAdaptable { - public static final int UNKNOWN_LINE_NUMBER= -1; - private IMember fMember; - private IMember fCalledMember; - private int fStart; - private int fEnd; - - private String fCallText; - private int fLineNumber; - - public CallLocation(IMember member, IMember calledMember, int start, int end, int lineNumber) { - this.fMember = member; - this.fCalledMember = calledMember; - this.fStart = start; - this.fEnd = end; - this.fLineNumber= lineNumber; - } - - /** - * @return IMethod - */ - public IMember getCalledMember() { - return fCalledMember; - } - - /** - * - */ - public int getEnd() { - return fEnd; - } - - public IMember getMember() { - return fMember; - } - - /** - * - */ - public int getStart() { - return fStart; - } - - public int getLineNumber() { - initCallTextAndLineNumber(); - return fLineNumber; - } - - public String getCallText() { - initCallTextAndLineNumber(); - return fCallText; - } - - private void initCallTextAndLineNumber() { - if (fCallText != null) { - return; - } - - IBuffer buffer= getBufferForMember(); - if (buffer == null || buffer.getLength() < fEnd) { //binary, without source attachment || buffer contents out of sync (bug 121900) - fCallText= ""; //$NON-NLS-1$ - fLineNumber= UNKNOWN_LINE_NUMBER; - return; - } - - fCallText= buffer.getText(fStart, (fEnd - fStart)); - - if (fLineNumber == UNKNOWN_LINE_NUMBER) { - Document document= new Document(buffer.getContents()); - try { - fLineNumber= document.getLineOfOffset(fStart) + 1; - } catch (BadLocationException e) { - JavaLanguageServerPlugin.logException(e); - } - } - } - - /** - * Returns the IBuffer for the IMember represented by this CallLocation. - * - * @return IBuffer for the IMember or null if the member doesn't have a buffer (for - * example if it is a binary file without source attachment). - */ - private IBuffer getBufferForMember() { - IBuffer buffer = null; - try { - IOpenable openable = fMember.getOpenable(); - if (openable != null && fMember.exists()) { - buffer = openable.getBuffer(); - } - } catch (JavaModelException e) { - JavaLanguageServerPlugin.log(e); - } - return buffer; - } - - @Override - public String toString() { - return getCallText(); - } - - @Override - @SuppressWarnings("unchecked") - public T getAdapter(Class adapter) { - if (IJavaElement.class.isAssignableFrom(adapter)) { - return (T) getMember(); - } - - return null; - } -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallSearchResultCollector.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallSearchResultCollector.java deleted file mode 100644 index b808b55961..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallSearchResultCollector.java +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation - * (report 36180: Callers/Callees view) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IMember; -import org.eclipse.jdt.core.IType; - -class CallSearchResultCollector { - /** - * A map from handle identifier ({@link String}) to {@link MethodCall}. - */ - private Map fCalledMembers; - - public CallSearchResultCollector() { - this.fCalledMembers = createCalledMethodsData(); - } - - /** - * @return a map from handle identifier ({@link String}) to {@link MethodCall} - */ - public Map getCallers() { - return fCalledMembers; - } - - protected void addMember(IMember member, IMember calledMember, int start, int end) { - addMember(member, calledMember, start, end, CallLocation.UNKNOWN_LINE_NUMBER); - } - - protected void addMember(IMember member, IMember calledMember, int start, int end, int lineNumber) { - if ((member != null) && (calledMember != null)) { - if (!isIgnored(calledMember)) { - MethodCall methodCall = fCalledMembers.get(calledMember.getHandleIdentifier()); - - if (methodCall == null) { - methodCall = new MethodCall(calledMember); - fCalledMembers.put(calledMember.getHandleIdentifier(), methodCall); - } - - methodCall.addCallLocation(new CallLocation(member, calledMember, start, - end, lineNumber)); - } - } - } - - protected Map createCalledMethodsData() { - return new HashMap<>(); - } - - /** - * Method isIgnored. - * @param enclosingElement - * @return boolean - */ - private boolean isIgnored(IMember enclosingElement) { - String fullyQualifiedName = getTypeOfElement(enclosingElement) - .getFullyQualifiedName(); - - return CallHierarchy.getDefault().isIgnored(fullyQualifiedName); - } - - private IType getTypeOfElement(IMember element) { - if (element.getElementType() == IJavaElement.TYPE) { - return (IType) element; - } - - return element.getDeclaringType(); - } -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CalleeAnalyzerVisitor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CalleeAnalyzerVisitor.java deleted file mode 100644 index 7e2603186b..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CalleeAnalyzerVisitor.java +++ /dev/null @@ -1,351 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation - * (report 36180: Callers/Callees view) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; -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.dom.ASTNode; -import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; -import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; -import org.eclipse.jdt.core.dom.BodyDeclaration; -import org.eclipse.jdt.core.dom.ClassInstanceCreation; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.ConstructorInvocation; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.SuperConstructorInvocation; -import org.eclipse.jdt.core.dom.SuperMethodInvocation; -import org.eclipse.jdt.core.search.IJavaSearchScope; -import org.eclipse.jdt.internal.corext.dom.Bindings; -import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor; -import org.eclipse.jdt.internal.corext.util.JavaModelUtil; -import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; - -class CalleeAnalyzerVisitor extends HierarchicalASTVisitor { - private final CallSearchResultCollector fSearchResults; - private final IMember fMember; - private final CompilationUnit fCompilationUnit; - private final IProgressMonitor fProgressMonitor; - private int fMethodEndPosition; - private int fMethodStartPosition; - - CalleeAnalyzerVisitor(IMember member, CompilationUnit compilationUnit, IProgressMonitor progressMonitor) { - fSearchResults = new CallSearchResultCollector(); - this.fMember = member; - this.fCompilationUnit= compilationUnit; - this.fProgressMonitor = progressMonitor; - - try { - ISourceRange sourceRange = member.getSourceRange(); - this.fMethodStartPosition = sourceRange.getOffset(); - this.fMethodEndPosition = fMethodStartPosition + sourceRange.getLength(); - } catch (JavaModelException jme) { - JavaLanguageServerPlugin.log(jme); - } - } - - /** - * @return a map from handle identifier ({@link String}) to {@link MethodCall} - */ - public Map getCallees() { - return fSearchResults.getCallers(); - } - - @Override - public boolean visit(ClassInstanceCreation node) { - progressMonitorWorked(1); - if (!isFurtherTraversalNecessary(node)) { - return false; - } - - if (isNodeWithinMethod(node)) { - addMethodCall(node.resolveConstructorBinding(), node); - } - - return true; - } - - /** - * Find all constructor invocations (this(...)) from the called method. - * Since we only traverse into the AST on the wanted method declaration, this method - * should not hit on more constructor invocations than those in the wanted method. - * - * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ConstructorInvocation) - */ - @Override - public boolean visit(ConstructorInvocation node) { - progressMonitorWorked(1); - if (!isFurtherTraversalNecessary(node)) { - return false; - } - - if (isNodeWithinMethod(node)) { - addMethodCall(node.resolveConstructorBinding(), node); - } - - return true; - } - - /** - * @see HierarchicalASTVisitor#visit(org.eclipse.jdt.core.dom.AbstractTypeDeclaration) - */ - @Override - public boolean visit(AbstractTypeDeclaration node) { - progressMonitorWorked(1); - if (!isFurtherTraversalNecessary(node)) { - return false; - } - - if (isNodeWithinMethod(node)) { - List bodyDeclarations= node.bodyDeclarations(); - for (Iterator iter= bodyDeclarations.iterator(); iter.hasNext(); ) { - BodyDeclaration bodyDeclaration= iter.next(); - if (bodyDeclaration instanceof MethodDeclaration) { - MethodDeclaration child= (MethodDeclaration) bodyDeclaration; - if (child.isConstructor()) { - addMethodCall(child.resolveBinding(), child.getName()); - } - } - } - return false; - } - - return true; - } - - /** - * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodDeclaration) - */ - @Override - public boolean visit(MethodDeclaration node) { - progressMonitorWorked(1); - return isFurtherTraversalNecessary(node); - } - - /** - * Find all method invocations from the called method. Since we only traverse into - * the AST on the wanted method declaration, this method should not hit on more - * method invocations than those in the wanted method. - * - * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodInvocation) - */ - @Override - public boolean visit(MethodInvocation node) { - progressMonitorWorked(1); - if (!isFurtherTraversalNecessary(node)) { - return false; - } - - if (isNodeWithinMethod(node)) { - addMethodCall(node.resolveMethodBinding(), node); - } - - return true; - } - - /** - * Find invocations of the supertype's constructor from the called method - * (=constructor). Since we only traverse into the AST on the wanted method - * declaration, this method should not hit on more method invocations than those in - * the wanted method. - * - * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SuperConstructorInvocation) - */ - @Override - public boolean visit(SuperConstructorInvocation node) { - progressMonitorWorked(1); - if (!isFurtherTraversalNecessary(node)) { - return false; - } - - if (isNodeWithinMethod(node)) { - addMethodCall(node.resolveConstructorBinding(), node); - } - - return true; - } - - /** - * Find all method invocations from the called method. Since we only traverse into - * the AST on the wanted method declaration, this method should not hit on more - * method invocations than those in the wanted method. - * @param node node to visit - * @return whether children should be visited - * - * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodInvocation) - */ - @Override - public boolean visit(SuperMethodInvocation node) { - progressMonitorWorked(1); - if (!isFurtherTraversalNecessary(node)) { - return false; - } - - if (isNodeWithinMethod(node)) { - addMethodCall(node.resolveMethodBinding(), node); - } - - return true; - } - - /** - * When an anonymous class declaration is reached, the traversal should not go further since it's not - * supposed to consider calls inside the anonymous inner class as calls from the outer method. - * - * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnonymousClassDeclaration) - */ - @Override - public boolean visit(AnonymousClassDeclaration node) { - return isNodeEnclosingMethod(node); - } - - - /** - * Adds the specified method binding to the search results. - * - * @param calledMethodBinding the called method binding - * @param node the AST node - */ - protected void addMethodCall(IMethodBinding calledMethodBinding, ASTNode node) { - try { - if (calledMethodBinding != null) { - fProgressMonitor.worked(1); - - ITypeBinding calledTypeBinding = calledMethodBinding.getDeclaringClass(); - IType calledType = null; - - if (!calledTypeBinding.isAnonymous()) { - calledType = (IType) calledTypeBinding.getJavaElement(); - } else { - if (!"java.lang.Object".equals(calledTypeBinding.getSuperclass().getQualifiedName())) { //$NON-NLS-1$ - calledType= (IType) calledTypeBinding.getSuperclass().getJavaElement(); - } else { - calledType = (IType) calledTypeBinding.getInterfaces()[0].getJavaElement(); - } - } - - IMethod calledMethod = findIncludingSupertypes(calledMethodBinding, - calledType, fProgressMonitor); - - IMember referencedMember= null; - if (calledMethod == null) { - if (calledMethodBinding.isConstructor() && calledMethodBinding.getParameterTypes().length == 0) { - referencedMember= calledType; - } - } else { - if (calledType.isInterface()) { - calledMethod = findImplementingMethods(calledMethod); - } - - if (!isIgnoredBySearchScope(calledMethod)) { - referencedMember= calledMethod; - } - } - final int position= node.getStartPosition(); - final int number= fCompilationUnit.getLineNumber(position); - fSearchResults.addMember(fMember, referencedMember, position, position + node.getLength(), number < 1 ? 1 : number); - } - } catch (JavaModelException jme) { - JavaLanguageServerPlugin.log(jme); - } - } - - private static IMethod findIncludingSupertypes(IMethodBinding method, IType type, IProgressMonitor pm) throws JavaModelException { - IMethod inThisType= Bindings.findMethod(method, type); - if (inThisType != null) { - return inThisType; - } - IType[] superTypes= JavaModelUtil.getAllSuperTypes(type, pm); - for (int i= 0; i < superTypes.length; i++) { - IMethod m= Bindings.findMethod(method, superTypes[i]); - if (m != null) { - return m; - } - } - return null; - } - - private boolean isIgnoredBySearchScope(IMethod enclosingElement) { - if (enclosingElement != null) { - return !getSearchScope().encloses(enclosingElement); - } else { - return false; - } - } - - private IJavaSearchScope getSearchScope() { - return CallHierarchy.getDefault().getSearchScope(); - } - - private boolean isNodeWithinMethod(ASTNode node) { - int nodeStartPosition = node.getStartPosition(); - int nodeEndPosition = nodeStartPosition + node.getLength(); - - if (nodeStartPosition < fMethodStartPosition) { - return false; - } - - if (nodeEndPosition > fMethodEndPosition) { - return false; - } - - return true; - } - - private boolean isNodeEnclosingMethod(ASTNode node) { - int nodeStartPosition = node.getStartPosition(); - int nodeEndPosition = nodeStartPosition + node.getLength(); - - if (nodeStartPosition < fMethodStartPosition && nodeEndPosition > fMethodEndPosition) { - // Is the method completely enclosed by the node? - return true; - } - return false; - } - - private boolean isFurtherTraversalNecessary(ASTNode node) { - return isNodeWithinMethod(node) || isNodeEnclosingMethod(node); - } - - private IMethod findImplementingMethods(IMethod calledMethod) { - Collection implementingMethods = CallHierarchy.getDefault() - .getImplementingMethods(calledMethod); - - if ((implementingMethods.size() == 0) || (implementingMethods.size() > 1)) { - return calledMethod; - } else { - return (IMethod) implementingMethods.iterator().next(); - } - } - - private void progressMonitorWorked(int work) { - if (fProgressMonitor != null) { - fProgressMonitor.worked(work); - if (fProgressMonitor.isCanceled()) { - throw new OperationCanceledException(); - } - } - } -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CalleeMethodWrapper.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CalleeMethodWrapper.java deleted file mode 100644 index 046cef5dca..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CalleeMethodWrapper.java +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation - * (report 36180: Callers/Callees view) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.jdt.core.IMember; -import org.eclipse.jdt.core.dom.CompilationUnit; - -class CalleeMethodWrapper extends MethodWrapper { - private Comparator fMethodWrapperComparator = new MethodWrapperComparator(); - - private static class MethodWrapperComparator implements Comparator { - @Override - public int compare(MethodWrapper m1, MethodWrapper m2) { - CallLocation callLocation1 = m1.getMethodCall().getFirstCallLocation(); - CallLocation callLocation2 = m2.getMethodCall().getFirstCallLocation(); - - if ((callLocation1 != null) && (callLocation2 != null)) { - if (callLocation1.getStart() == callLocation2.getStart()) { - return callLocation1.getEnd() - callLocation2.getEnd(); - } - - return callLocation1.getStart() - callLocation2.getStart(); - } - - return 0; - } - } - - public CalleeMethodWrapper(MethodWrapper parent, MethodCall methodCall) { - super(parent, methodCall); - } - - /* Returns the calls sorted after the call location - * @see org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper#getCalls() - */ - @Override - public MethodWrapper[] getCalls(IProgressMonitor progressMonitor) { - MethodWrapper[] result = super.getCalls(progressMonitor); - Arrays.sort(result, fMethodWrapperComparator); - - return result; - } - - @Override - protected String getTaskName() { - return CallHierarchyMessages.CalleeMethodWrapper_taskname; - } - - /* - * @see org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper#createMethodWrapper(org.eclipse.jdt.internal.corext.callhierarchy.MethodCall) - */ - @Override - protected MethodWrapper createMethodWrapper(MethodCall methodCall) { - return new CalleeMethodWrapper(this, methodCall); - } - - /* - * @see org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper#canHaveChildren() - */ - @Override - public boolean canHaveChildren() { - return true; - } - - /** - * Find callees called from the current method. - * @see org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper#findChildren(org.eclipse.core.runtime.IProgressMonitor) - */ - @Override - protected Map findChildren(IProgressMonitor progressMonitor) { - IMember member= getMember(); - if (member.exists()) { - CompilationUnit cu= CallHierarchy.getCompilationUnitNode(member, true); - if (progressMonitor != null) { - progressMonitor.worked(5); - } - - if (cu != null) { - CalleeAnalyzerVisitor visitor = new CalleeAnalyzerVisitor(member, cu, progressMonitor); - - cu.accept(visitor); - return visitor.getCallees(); - } - } - return new HashMap<>(0); - } -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallerMethodWrapper.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallerMethodWrapper.java deleted file mode 100644 index 2b16b2d21d..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/CallerMethodWrapper.java +++ /dev/null @@ -1,213 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * 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) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.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.SubProgressMonitor; -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.corext.util.JdtFlags; -import org.eclipse.jdt.internal.corext.util.SearchUtils; -import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; - -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 CallHierarchy.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.corext.callhierarchy.MethodWrapper#findChildren(org.eclipse.core.runtime.IProgressMonitor) - */ - @Override - protected Map findChildren(IProgressMonitor progressMonitor) { - try { - - IProgressMonitor monitor= new SubProgressMonitor(progressMonitor, 95, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL); - - 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) { - JavaLanguageServerPlugin.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 true if in expand with constructors mode, false 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 true if in expand with constructors mode, false - * otherwise - * @since 3.5 - */ - public void setExpandWithConstructors(boolean value) { - fExpandWithConstructors= value; - fIsExpandWithConstructorsSet= true; - - } - - /** - * Tells whether the expand with constructors mode has been set. - * - * @return true if expand with constructors mode has been set explicitly, false otherwise - * @see #setExpandWithConstructors(boolean) - * @since 3.5 - */ - public boolean isExpandWithConstructorsSet() { - return fIsExpandWithConstructorsSet; - } - -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/IImplementorFinder.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/IImplementorFinder.java deleted file mode 100644 index 8011e4662e..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/IImplementorFinder.java +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation - * (report 36180: Callers/Callees view) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import java.util.Collection; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.jdt.core.IType; - -public interface IImplementorFinder { - - /** - * Find implementors of the specified IType instance. - */ - public abstract Collection findImplementingTypes(IType type, - IProgressMonitor progressMonitor); - - /** - * Find interfaces which are implemented by the specified IType instance. - */ - public abstract Collection findInterfaces(IType type, IProgressMonitor progressMonitor); -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/Implementors.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/Implementors.java deleted file mode 100644 index f6e0b96036..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/Implementors.java +++ /dev/null @@ -1,194 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation - * (report 36180: Callers/Callees view) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import java.util.ArrayList; -import java.util.Collection; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.SubProgressMonitor; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IMember; -import org.eclipse.jdt.core.IMethod; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; - -/** - * The main plugin class to be used in the desktop. - */ -public class Implementors { - private static IImplementorFinder[] IMPLEMENTOR_FINDERS= new IImplementorFinder[] { new JavaImplementorFinder() }; - private static Implementors fgInstance; - - /** - * Returns the shared instance. - */ - public static Implementors getInstance() { - if (fgInstance == null) { - fgInstance = new Implementors(); - } - - return fgInstance; - } - - /** - * Searches for implementors of the specified Java elements. Currently, only IMethod - * instances are searched for. Also, only the first element of the elements - * parameter is taken into consideration. - * - * @param elements - * - * @return An array of found implementing Java elements (currently only IMethod - * instances) - */ - public IJavaElement[] searchForImplementors(IJavaElement[] elements, - IProgressMonitor progressMonitor) { - if ((elements != null) && (elements.length > 0)) { - IJavaElement element = elements[0]; - - try { - if (element instanceof IMember) { - IMember member = (IMember) element; - IType type = member.getDeclaringType(); - - if (type.isInterface()) { - IType[] implementingTypes = findImplementingTypes(type, - progressMonitor); - - if (member.getElementType() == IJavaElement.METHOD) { - return findMethods((IMethod)member, implementingTypes, progressMonitor); - } else { - return implementingTypes; - } - } - } - } catch (JavaModelException e) { - JavaLanguageServerPlugin.log(e); - } - } - - return null; - } - - /** - * Searches for interfaces which are implemented by the declaring classes of the - * specified Java elements. Currently, only IMethod instances are searched for. - * Also, only the first element of the elements parameter is taken into - * consideration. - * - * @param elements - * - * @return An array of found interfaces implemented by the declaring classes of the - * specified Java elements (currently only IMethod instances) - */ - public IJavaElement[] searchForInterfaces(IJavaElement[] elements, - IProgressMonitor progressMonitor) { - if ((elements != null) && (elements.length > 0)) { - IJavaElement element = elements[0]; - - if (element instanceof IMember) { - IMember member = (IMember) element; - IType type = member.getDeclaringType(); - - IType[] implementingTypes = findInterfaces(type, progressMonitor); - - if (!progressMonitor.isCanceled()) { - if (member.getElementType() == IJavaElement.METHOD) { - return findMethods((IMethod)member, implementingTypes, progressMonitor); - } else { - return implementingTypes; - } - } - } - } - - return null; - } - - private IImplementorFinder[] getImplementorFinders() { - return IMPLEMENTOR_FINDERS; - } - - private IType[] findImplementingTypes(IType type, IProgressMonitor progressMonitor) { - Collection implementingTypes = new ArrayList<>(); - - IImplementorFinder[] finders = getImplementorFinders(); - - for (int i = 0; (i < finders.length) && !progressMonitor.isCanceled(); i++) { - Collection types = finders[i].findImplementingTypes(type, - new SubProgressMonitor(progressMonitor, 10, - SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); - - if (types != null) { - implementingTypes.addAll(types); - } - } - - return implementingTypes.toArray(new IType[implementingTypes.size()]); - } - - private IType[] findInterfaces(IType type, IProgressMonitor progressMonitor) { - Collection interfaces = new ArrayList<>(); - - IImplementorFinder[] finders = getImplementorFinders(); - - for (int i = 0; (i < finders.length) && !progressMonitor.isCanceled(); i++) { - Collection types = finders[i].findInterfaces(type, - new SubProgressMonitor(progressMonitor, 10, - SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); - - if (types != null) { - interfaces.addAll(types); - } - } - - return interfaces.toArray(new IType[interfaces.size()]); - } - - /** - * Finds IMethod instances on the specified IType instances with identical signatures - * as the specified IMethod parameter. - * - * @param method The method to find "equals" of. - * @param types The types in which the search is performed. - * - * @return An array of methods which match the method parameter. - */ - private IJavaElement[] findMethods(IMethod method, IType[] types, - IProgressMonitor progressMonitor) { - Collection foundMethods = new ArrayList<>(); - - SubProgressMonitor subProgressMonitor = new SubProgressMonitor(progressMonitor, - 10, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL); - subProgressMonitor.beginTask("", types.length); //$NON-NLS-1$ - - try { - for (int i = 0; i < types.length; i++) { - IType type = types[i]; - IMethod[] methods = type.findMethods(method); - - if (methods != null) { - for (int j = 0; j < methods.length; j++) { - foundMethods.add(methods[j]); - } - } - - subProgressMonitor.worked(1); - } - } finally { - subProgressMonitor.done(); - } - - return foundMethods.toArray(new IJavaElement[foundMethods.size()]); - } -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/JavaImplementorFinder.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/JavaImplementorFinder.java deleted file mode 100644 index ba5c7c4dae..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/JavaImplementorFinder.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation - * (report 36180: Callers/Callees view) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.ITypeHierarchy; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; - -public class JavaImplementorFinder implements IImplementorFinder { - @Override - public Collection findImplementingTypes(IType type, IProgressMonitor progressMonitor) { - ITypeHierarchy typeHierarchy; - - try { - typeHierarchy = type.newTypeHierarchy(progressMonitor); - - IType[] implementingTypes = typeHierarchy.getAllClasses(); - HashSet result = new HashSet<>(Arrays.asList(implementingTypes)); - - return result; - } catch (JavaModelException e) { - JavaLanguageServerPlugin.log(e); - } - - return null; - } - - @Override - public Collection findInterfaces(IType type, IProgressMonitor progressMonitor) { - ITypeHierarchy typeHierarchy; - - try { - typeHierarchy = type.newSupertypeHierarchy(progressMonitor); - - IType[] interfaces = typeHierarchy.getAllSuperInterfaces(type); - HashSet result = new HashSet<>(Arrays.asList(interfaces)); - - return result; - } catch (JavaModelException e) { - JavaLanguageServerPlugin.log(e); - } - - return null; - } -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodCall.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodCall.java deleted file mode 100644 index fa8981b9aa..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodCall.java +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation - * (report 36180: Callers/Callees view) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.eclipse.jdt.core.IMember; - -public class MethodCall { - private IMember fMember; - private List fCallLocations; - - /** - * @param enclosingElement - */ - public MethodCall(IMember enclosingElement) { - this.fMember = enclosingElement; - } - - /** - * - */ - public Collection getCallLocations() { - return fCallLocations; - } - - public CallLocation getFirstCallLocation() { - if ((fCallLocations != null) && !fCallLocations.isEmpty()) { - return fCallLocations.get(0); - } else { - return null; - } - } - - public boolean hasCallLocations() { - return fCallLocations != null && fCallLocations.size() > 0; - } - - /** - * @return Object - */ - public String getKey() { - return getMember().getHandleIdentifier(); - } - - /** - * - */ - public IMember getMember() { - return fMember; - } - - /** - * @param location - */ - public void addCallLocation(CallLocation location) { - if (fCallLocations == null) { - fCallLocations = new ArrayList<>(); - } - - fCallLocations.add(location); - } -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodReferencesSearchRequestor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodReferencesSearchRequestor.java deleted file mode 100644 index 25f386973d..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodReferencesSearchRequestor.java +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation - * (report 36180: Callers/Callees view) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import java.util.Map; - -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IMember; -import org.eclipse.jdt.core.search.SearchMatch; -import org.eclipse.jdt.core.search.SearchRequestor; - -class MethodReferencesSearchRequestor extends SearchRequestor { - private CallSearchResultCollector fSearchResults; - private boolean fRequireExactMatch = true; - - MethodReferencesSearchRequestor() { - fSearchResults = new CallSearchResultCollector(); - } - - public Map getCallers() { - return fSearchResults.getCallers(); - } - - @Override - public void acceptSearchMatch(SearchMatch match) { - if (fRequireExactMatch && (match.getAccuracy() != SearchMatch.A_ACCURATE)) { - return; - } - - if (match.isInsideDocComment()) { - return; - } - - if (match.getElement() != null && match.getElement() instanceof IMember) { - IMember member= (IMember) match.getElement(); - switch (member.getElementType()) { - case IJavaElement.METHOD: - case IJavaElement.TYPE: - case IJavaElement.FIELD: - case IJavaElement.INITIALIZER: - fSearchResults.addMember(member, member, match.getOffset(), match.getOffset()+match.getLength()); - break; - } - } - } -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodWrapper.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodWrapper.java deleted file mode 100644 index 7be80d401f..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/MethodWrapper.java +++ /dev/null @@ -1,363 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * 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) - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import org.eclipse.core.runtime.Assert; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.core.runtime.PlatformObject; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IMember; -import org.eclipse.jdt.core.search.IJavaSearchConstants; - -/** - * This class represents the general parts of a method call (either to or from a - * method). - * - */ -public abstract class MethodWrapper extends PlatformObject { - private Map fElements = null; - - /* - * A cache of previously found methods. This cache should be searched - * before adding a "new" method object reference to the list of elements. - * This way previously found methods won't be searched again. - */ - private Map> fMethodCache; - private final MethodCall fMethodCall; - private final MethodWrapper fParent; - private int fLevel; - /** - * One of {@link IJavaSearchConstants#REFERENCES}, {@link IJavaSearchConstants#READ_ACCESSES}, - * or {@link IJavaSearchConstants#WRITE_ACCESSES}, or 0 if not set. Only used for root wrappers. - */ - private int fFieldSearchMode; - - public MethodWrapper(MethodWrapper parent, MethodCall methodCall) { - Assert.isNotNull(methodCall); - - if (parent == null) { - setMethodCache(new HashMap>()); - fLevel = 1; - } else { - setMethodCache(parent.getMethodCache()); - fLevel = parent.getLevel() + 1; - } - - this.fMethodCall = methodCall; - this.fParent = parent; - } - - @SuppressWarnings("unchecked") - @Override - public T getAdapter(Class adapter) { - if (adapter == IJavaElement.class) { - return (T) getMember(); - } else { - return null; - } - } - - public MethodWrapper[] getCalls(IProgressMonitor progressMonitor) { - if (fElements == null) { - doFindChildren(progressMonitor); - } - - MethodWrapper[] result = new MethodWrapper[fElements.size()]; - int i = 0; - - for (Iterator iter = fElements.keySet().iterator(); iter.hasNext();) { - MethodCall methodCall = getMethodCallFromMap(fElements, iter.next()); - result[i++] = createMethodWrapper(methodCall); - } - - return result; - } - - public int getLevel() { - return fLevel; - } - - public IMember getMember() { - return getMethodCall().getMember(); - } - - public MethodCall getMethodCall() { - return fMethodCall; - } - - public String getName() { - if (getMethodCall() != null) { - return getMethodCall().getMember().getElementName(); - } else { - return ""; //$NON-NLS-1$ - } - } - - public MethodWrapper getParent() { - return fParent; - } - - public int getFieldSearchMode() { - if (fFieldSearchMode != 0) { - return fFieldSearchMode; - } - MethodWrapper parent= getParent(); - while (parent != null) { - if (parent.fFieldSearchMode != 0) { - return parent.fFieldSearchMode; - } else { - parent= parent.getParent(); - } - } - return IJavaSearchConstants.REFERENCES; - } - - public void setFieldSearchMode(int fieldSearchMode) { - fFieldSearchMode= fieldSearchMode; - } - - @Override - public boolean equals(Object oth) { - if (this == oth) { - return true; - } - - if (oth == null) { - return false; - } - - if (oth.getClass() != getClass()) { - return false; - } - - MethodWrapper other = (MethodWrapper) oth; - - if (this.fParent == null) { - if (other.fParent != null) { - return false; - } - } else { - if (!this.fParent.equals(other.fParent)) { - return false; - } - } - - if (this.getMethodCall() == null) { - if (other.getMethodCall() != null) { - return false; - } - } else { - if (!this.getMethodCall().equals(other.getMethodCall())) { - return false; - } - } - - return true; - } - - @Override - public int hashCode() { - final int PRIME = 1000003; - int result = 0; - - if (fParent != null) { - result = (PRIME * result) + fParent.hashCode(); - } - - if (getMethodCall() != null) { - result = (PRIME * result) + getMethodCall().getMember().hashCode(); - } - - return result; - } - - private void setMethodCache(Map> methodCache) { - fMethodCache = methodCache; - } - - protected abstract String getTaskName(); - - private void addCallToCache(MethodCall methodCall) { - Map cachedCalls = lookupMethod(this.getMethodCall()); - cachedCalls.put(methodCall.getKey(), methodCall); - } - - /** - * Creates a method wrapper for the child of the receiver. - * - * @param methodCall the method call - * @return the method wrapper - */ - protected abstract MethodWrapper createMethodWrapper(MethodCall methodCall); - - private void doFindChildren(IProgressMonitor progressMonitor) { - Map existingResults = lookupMethod(getMethodCall()); - - if (existingResults != null && !existingResults.isEmpty()) { - fElements = new HashMap<>(); - fElements.putAll(existingResults); - } else { - initCalls(); - - if (progressMonitor != null) { - progressMonitor.beginTask(getTaskName(), 100); - } - - try { - performSearch(progressMonitor); - } catch (OperationCanceledException e){ - fElements= null; - throw e; - } finally { - if (progressMonitor != null) { - progressMonitor.done(); - } - } - } - } - - /** - * Determines if the method represents a recursion call (i.e. whether the - * method call is already in the cache.) - * - * @return True if the call is part of a recursion - */ - public boolean isRecursive() { - if (fParent instanceof RealCallers) { - return false; - } - MethodWrapper current = getParent(); - - while (current != null) { - if (getMember().getHandleIdentifier().equals(current.getMember() - .getHandleIdentifier())) { - return true; - } - - current = current.getParent(); - } - - return false; - } - - /** - * @return whether this member can have children - */ - public abstract boolean canHaveChildren(); - - /** - * This method finds the children of the current IMember (either callers or - * callees, depending on the concrete subclass). - * @param progressMonitor a progress monitor - * - * @return a map from handle identifier ({@link String}) to {@link MethodCall} - */ - protected abstract Map findChildren(IProgressMonitor progressMonitor); - - private Map> getMethodCache() { - return fMethodCache; - } - - private void initCalls() { - this.fElements = new HashMap<>(); - - initCacheForMethod(); - } - - /** - * Looks up a previously created search result in the "global" cache. - * @param methodCall the method call - * @return the List of previously found search results - */ - private Map lookupMethod(MethodCall methodCall) { - return getMethodCache().get(methodCall.getKey()); - } - - private void performSearch(IProgressMonitor progressMonitor) { - fElements = findChildren(progressMonitor); - - for (Iterator iter = fElements.keySet().iterator(); iter.hasNext();) { - checkCanceled(progressMonitor); - - MethodCall methodCall = getMethodCallFromMap(fElements, iter.next()); - addCallToCache(methodCall); - } - } - - private MethodCall getMethodCallFromMap(Map elements, String key) { - return elements.get(key); - } - - private void initCacheForMethod() { - Map cachedCalls = new HashMap<>(); - getMethodCache().put(this.getMethodCall().getKey(), cachedCalls); - } - - /** - * Checks with the progress monitor to see whether the creation of the type hierarchy - * should be canceled. Should be regularly called - * so that the user can cancel. - * - * @param progressMonitor the progress monitor - * @exception OperationCanceledException if cancelling the operation has been requested - * @see IProgressMonitor#isCanceled - */ - protected void checkCanceled(IProgressMonitor progressMonitor) { - if (progressMonitor != null && progressMonitor.isCanceled()) { - throw new OperationCanceledException(); - } - } - - /** - * Allows a visitor to traverse the call hierarchy. The visiting is stopped when - * a recursive node is reached. - * - * @param visitor the visitor - * @param progressMonitor the progress monitor - */ - public void accept(CallHierarchyVisitor visitor, IProgressMonitor progressMonitor) { - if (getParent() != null && getParent().isRecursive()) { - return; - } - checkCanceled(progressMonitor); - - visitor.preVisit(this); - if (visitor.visit(this)) { - MethodWrapper[] methodWrappers= getCalls(progressMonitor); - for (int i= 0; i < methodWrappers.length; i++) { - methodWrappers[i].accept(visitor, progressMonitor); - } - } - visitor.postVisit(this); - - if (progressMonitor != null) { - progressMonitor.worked(1); - } - } - - /** - * Removes the given method call from the cache. - * - * @since 3.6 - */ - public void removeFromCache() { - fElements= null; - fMethodCache.remove(getMethodCall().getKey()); - } -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/RealCallers.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/RealCallers.java deleted file mode 100644 index 16e6a72fac..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corext/callhierarchy/RealCallers.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.corext.callhierarchy; - -/** - * Class for the real callers. - * - * @since 3.5 - */ - public class RealCallers extends CallerMethodWrapper { - - /** - * Sets the parent method wrapper. - * - * @param methodWrapper the method wrapper - * @param methodCall the method call - */ - public RealCallers(MethodWrapper methodWrapper, MethodCall methodCall) { - super(methodWrapper, methodCall); - } - - @Override - public boolean canHaveChildren() { - return true; - } - - @Override - public boolean isRecursive() { - return false; - } - } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyHandler.java index c122ec9302..f3660acb5c 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyHandler.java @@ -11,11 +11,11 @@ package org.eclipse.jdt.ls.core.internal.handlers; import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.toList; import static org.eclipse.jdt.core.ICompilationUnit.NO_AST; import static org.eclipse.jdt.core.IJavaElement.CLASS_FILE; import static org.eclipse.jdt.core.IJavaElement.COMPILATION_UNIT; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -37,56 +37,90 @@ import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.corext.callhierarchy.CallHierarchyCore; +import org.eclipse.jdt.internal.corext.callhierarchy.CallLocation; +import org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper; import org.eclipse.jdt.ls.core.internal.JDTUtils; import org.eclipse.jdt.ls.core.internal.JDTUtils.LocationType; import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; -import org.eclipse.jdt.ls.core.internal.corext.callhierarchy.CallHierarchy; -import org.eclipse.jdt.ls.core.internal.corext.callhierarchy.CallLocation; -import org.eclipse.jdt.ls.core.internal.corext.callhierarchy.MethodWrapper; -import org.eclipse.lsp4j.CallHierarchyDirection; +import org.eclipse.lsp4j.CallHierarchyIncomingCall; +import org.eclipse.lsp4j.CallHierarchyIncomingCallsParams; import org.eclipse.lsp4j.CallHierarchyItem; -import org.eclipse.lsp4j.CallHierarchyParams; +import org.eclipse.lsp4j.CallHierarchyOutgoingCall; +import org.eclipse.lsp4j.CallHierarchyOutgoingCallsParams; +import org.eclipse.lsp4j.CallHierarchyPrepareParams; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.Range; -import org.eclipse.lsp4j.services.TextDocumentService; +import org.eclipse.lsp4j.SymbolTag; -/** - * Handler for the {@link TextDocumentService#callHierarchy(CallHierarchyParams) - * textDocument/callHierarchy} language server method. - */ public class CallHierarchyHandler { - protected static ThreadLocal THREAD_LOCAL = new ThreadLocal<>(); - - public CallHierarchyItem callHierarchy(CallHierarchyParams params, IProgressMonitor monitor) { + public List prepareCallHierarchy(CallHierarchyPrepareParams params, IProgressMonitor monitor) { Assert.isNotNull(params, "params"); - Assert.isLegal(params.getResolve() >= 0, "'resolve' must a non-negative integer. Was: " + params.getResolve()); - CallHierarchyDirection direction = params.getDirection() == null ? CallHierarchyDirection.Incoming : params.getDirection(); String uri = params.getTextDocument().getUri(); int line = params.getPosition().getLine(); int character = params.getPosition().getCharacter(); - int resolve = params.getResolve(); try { - return getCallHierarchyItemAt(uri, line, character, resolve, direction, monitor); + IMember candidate = getCallHierarchyElement(uri, line, character, monitor); + if (candidate == null) { + return null; + } + checkMonitor(monitor); + return Arrays.asList(toCallHierarchyItem(candidate)); } catch (OperationCanceledException e) { - return THREAD_LOCAL.get(); + // do nothing } catch (JavaModelException e) { JavaLanguageServerPlugin.log(e); - } finally { - if (THREAD_LOCAL.get() != null) { - THREAD_LOCAL.set(null); - } } + return null; } - private CallHierarchyItem getCallHierarchyItemAt(String uri, int line, int character, int resolve, CallHierarchyDirection direction, IProgressMonitor monitor) throws JavaModelException { + public List callHierarchyIncomingCalls(CallHierarchyIncomingCallsParams params, IProgressMonitor monitor) { + Assert.isNotNull(params, "params"); + + CallHierarchyItem item = params.getItem(); + Assert.isNotNull(item, "call item"); + Position position = item.getSelectionRange().getStart(); + int line = position.getLine(); + int character = position.getCharacter(); + + try { + return getIncomingCallItemsAt(item.getUri(), line, character, monitor); + } catch (JavaModelException e) { + JavaLanguageServerPlugin.log(e); + } catch (OperationCanceledException e) { + // do nothing + } + + return null; + } + + public List callHierarchyOutgoingCalls(CallHierarchyOutgoingCallsParams params, IProgressMonitor monitor) { + Assert.isNotNull(params, "params"); + + CallHierarchyItem item = params.getItem(); + Assert.isNotNull(item, "call item"); + Position position = item.getSelectionRange().getStart(); + int line = position.getLine(); + int character = position.getCharacter(); + + try { + return getOutgoingCallItemsAt(item.getUri(), line, character, monitor); + } catch (JavaModelException e) { + JavaLanguageServerPlugin.log(e); + } catch (OperationCanceledException e) { + // do nothing + } + + return null; + } + + private IMember getCallHierarchyElement(String uri, int line, int character, IProgressMonitor monitor) throws JavaModelException { Assert.isNotNull(uri, "uri"); - Assert.isLegal(resolve >= 0, "Expected a non negative integer for 'resolve'. Was: " + resolve); - Assert.isNotNull(direction, "direction"); ITypeRoot root = JDTUtils.resolveTypeRoot(uri); if (root == null) { @@ -107,7 +141,7 @@ private CallHierarchyItem getCallHierarchyItemAt(String uri, int line, int chara IMember candidate = null; int offset = JsonRpcHelpers.toOffset(root, line, character); List selectedElements = codeResolve(root, offset); - Stream possibleElements = selectedElements.stream().filter(CallHierarchy::isPossibleInputElement); + Stream possibleElements = selectedElements.stream().filter(CallHierarchyCore::isPossibleInputElement); Optional firstElement = possibleElements.findFirst(); if (firstElement.isPresent() && firstElement.get() instanceof IMember) { candidate = (IMember) firstElement.get(); @@ -121,14 +155,69 @@ private CallHierarchyItem getCallHierarchyItemAt(String uri, int line, int chara } } + return candidate; + } + + private List getIncomingCallItemsAt(String uri, int line, int character, IProgressMonitor monitor) throws JavaModelException { + IMember candidate = getCallHierarchyElement(uri, line, character, monitor); + if (candidate == null) { + return null; + } + checkMonitor(monitor); - MethodWrapper wrapper = toMethodWrapper(candidate, direction); + MethodWrapper wrapper = toMethodWrapper(candidate, true); if (wrapper == null) { return null; } - return toCallHierarchyItem(wrapper, resolve, monitor); + MethodWrapper[] calls = wrapper.getCalls(monitor); + if (calls == null) { + return null; + } + + List result = new ArrayList<>(); + for (MethodWrapper call : calls) { + CallHierarchyItem symbol = toCallHierarchyItem(call.getMember()); + List ranges = toCallRanges(call.getMethodCall().getCallLocations()); + CallHierarchyIncomingCall incomingCall = new CallHierarchyIncomingCall(); + incomingCall.setFrom(symbol); + incomingCall.setFromRanges(ranges.toArray(new Range[0])); + result.add(incomingCall); + } + + return result; + } + + private List getOutgoingCallItemsAt(String uri, int line, int character, IProgressMonitor monitor) throws JavaModelException { + IMember candidate = getCallHierarchyElement(uri, line, character, monitor); + if (candidate == null) { + return null; + } + + checkMonitor(monitor); + + MethodWrapper wrapper = toMethodWrapper(candidate, false); + if (wrapper == null) { + return null; + } + + MethodWrapper[] calls = wrapper.getCalls(monitor); + if (calls == null) { + return null; + } + + List result = new ArrayList<>(); + for (MethodWrapper call : calls) { + CallHierarchyItem symbol = toCallHierarchyItem(call.getMember()); + List ranges = toCallRanges(call.getMethodCall().getCallLocations()); + CallHierarchyOutgoingCall outgoingCall = new CallHierarchyOutgoingCall(); + outgoingCall.setTo(symbol); + outgoingCall.setFromRanges(ranges.toArray(new Range[0])); + result.add(outgoingCall); + } + + return result; } private List codeResolve(IJavaElement input, int offset) throws JavaModelException { @@ -138,13 +227,13 @@ private List codeResolve(IJavaElement input, int offset) throws Ja return emptyList(); } - private MethodWrapper toMethodWrapper(IMember member, CallHierarchyDirection direction) { + private MethodWrapper toMethodWrapper(IMember member, boolean isIncomingCall) { Assert.isNotNull(member, "member"); IMember[] members = { member }; - CallHierarchy callHierarchy = CallHierarchy.getDefault(); + CallHierarchyCore callHierarchy = CallHierarchyCore.getDefault(); final MethodWrapper[] result; - if (direction == CallHierarchyDirection.Incoming) { + if (isIncomingCall) { result = callHierarchy.getCallerRoots(members); } else { result = callHierarchy.getCalleeRoots(members); @@ -155,58 +244,43 @@ private MethodWrapper toMethodWrapper(IMember member, CallHierarchyDirection dir return result[0]; } - private CallHierarchyItem toCallHierarchyItem(MethodWrapper wrapper, int resolve, IProgressMonitor monitor) { - checkMonitor(monitor); - - if (wrapper == null || wrapper.getMember() == null) { - return null; + private CallHierarchyItem toCallHierarchyItem(IJavaElement member) throws JavaModelException { + Location fullLocation = getLocation(member, LocationType.FULL_RANGE); + Range range = fullLocation.getRange(); + String uri = fullLocation.getUri(); + CallHierarchyItem item = new CallHierarchyItem(); + item.setName(JDTUtils.getName(member)); + item.setKind(JDTUtils.getSymbolKind(member)); + item.setRange(range); + item.setSelectionRange(getLocation(member, LocationType.NAME_RANGE).getRange()); + item.setUri(uri); + item.setDetail(JDTUtils.getDetail(member)); + if (JDTUtils.isDeprecated(member)) { + item.setTags(new SymbolTag[] { SymbolTag.Deprecated }); } - try { - IMember member = wrapper.getMember(); - Location fullLocation = getLocation(member, LocationType.FULL_RANGE); - Range range = fullLocation.getRange(); - String uri = fullLocation.getUri(); - CallHierarchyItem item = new CallHierarchyItem(); - item.setName(JDTUtils.getName(member)); - item.setKind(JDTUtils.getSymbolKind(member)); - item.setRange(range); - item.setSelectionRange(getLocation(member, LocationType.NAME_RANGE).getRange()); - item.setUri(uri); - item.setDetail(JDTUtils.getDetail(member)); - item.setDeprecated(JDTUtils.isDeprecated(member)); - - Collection callLocations = wrapper.getMethodCall().getCallLocations(); - // The `callLocations` should be `null` for the root item. - if (callLocations != null) { - item.setCallLocations(callLocations.stream().map(location -> { - IOpenable openable = location.getMember().getCompilationUnit(); - if (openable == null) { - openable = location.getMember().getTypeRoot(); - } - int[] start = JsonRpcHelpers.toLine(openable, location.getStart()); - int[] end = JsonRpcHelpers.toLine(openable, location.getEnd()); - Assert.isNotNull(start, "start"); - Assert.isNotNull(end, "end"); - Assert.isLegal(start[0] == end[0], "Expected equal start and end lines. Start was: " + Arrays.toString(start) + " End was:" + Arrays.toString(end)); - Range callRange = new Range(new Position(start[0], start[1]), new Position(end[0], end[1])); - return new Location(uri, callRange); - }).collect(toList())); - } - - // Set the copy of the unresolved item to the thread local, so that we can return with it in case of user abort. (`monitor#cancel()`) - if (THREAD_LOCAL.get() == null) { - THREAD_LOCAL.set(shallowCopy(item)); - } + return item; + } - if (resolve > 0) { - item.setCalls(Arrays.stream(wrapper.getCalls(monitor)).map(w -> toCallHierarchyItem(w, resolve - 1, monitor)).collect(toList())); + private List toCallRanges(Collection callLocations) { + List ranges = new ArrayList<>(); + if (callLocations != null) { + for (CallLocation location : callLocations) { + IOpenable openable = location.getMember().getCompilationUnit(); + if (openable == null) { + openable = location.getMember().getTypeRoot(); + } + int[] start = JsonRpcHelpers.toLine(openable, location.getStart()); + int[] end = JsonRpcHelpers.toLine(openable, location.getEnd()); + Assert.isNotNull(start, "start"); + Assert.isNotNull(end, "end"); + // Assert.isLegal(start[0] == end[0], "Expected equal start and end lines. Start was: " + Arrays.toString(start) + " End was:" + Arrays.toString(end)); + Range callRange = new Range(new Position(start[0], start[1]), new Position(end[0], end[1])); + ranges.add(callRange); } - return item; - } catch (JavaModelException e) { - JavaLanguageServerPlugin.logException("Error when converting to a call hierarchy item.", e); } - return null; + + return ranges; } /** @@ -218,23 +292,6 @@ private void checkMonitor(IProgressMonitor monitor) { } } - /** - * Returns with a copy of the argument without the - * {@link CallHierarchyItem#getCalls() calls} set. - */ - private CallHierarchyItem shallowCopy(CallHierarchyItem other) { - CallHierarchyItem copy = new CallHierarchyItem(); - copy.setName(other.getName()); - copy.setDetail(other.getDetail()); - copy.setKind(other.getKind()); - copy.setDeprecated(other.getDeprecated()); - copy.setUri(other.getUri()); - copy.setRange(other.getRange()); - copy.setSelectionRange(other.getSelectionRange()); - copy.setCallLocations(other.getCallLocations()); - return copy; - } - /** * Gets the location of the Java {@code element} based on the desired * {@code locationType}. diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyResolveHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyResolveHandler.java deleted file mode 100644 index 7dffe88143..0000000000 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyResolveHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 TypeFox and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * TypeFox - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.handlers; - -import org.eclipse.core.runtime.Assert; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.lsp4j.CallHierarchyItem; -import org.eclipse.lsp4j.CallHierarchyParams; -import org.eclipse.lsp4j.ResolveCallHierarchyItemParams; -import org.eclipse.lsp4j.TextDocumentIdentifier; -import org.eclipse.lsp4j.services.TextDocumentService; - -/** - * Handler for the - * {@link TextDocumentService#resolveCallHierarchy(org.eclipse.lsp4j.ResolveCallHierarchyItemParams) - * callHierarchy/resolve} LS method. - */ -public class CallHierarchyResolveHandler extends CallHierarchyHandler { - - public CallHierarchyItem resolve(ResolveCallHierarchyItemParams params, IProgressMonitor monitor) { - Assert.isNotNull(params, "params"); - - return callHierarchy(toCallHierarchyParams(params), monitor); - } - - private CallHierarchyParams toCallHierarchyParams(ResolveCallHierarchyItemParams params) { - Assert.isNotNull(params.getItem(), "params.item"); - Assert.isNotNull(params.getDirection(), "params.direction"); - - CallHierarchyParams result = new CallHierarchyParams(); - result.setDirection(params.getDirection()); - result.setResolve(params.getResolve()); - CallHierarchyItem item = params.getItem(); - result.setTextDocument(new TextDocumentIdentifier(item.getUri())); - result.setPosition(item.getRange().getStart()); - return result; - } - -} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionResolveHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionResolveHandler.java index ba9076e5e1..1c9948df35 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionResolveHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionResolveHandler.java @@ -18,6 +18,7 @@ import java.io.Reader; import java.util.Map; +import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.eclipse.core.runtime.IProgressMonitor; @@ -140,7 +141,7 @@ public CompletionItem resolve(CompletionItem param, IProgressMonitor monitor) { String javadoc = null; try { final IMember curMember = member; - javadoc = new SimpleTimeLimiter().callWithTimeout(() -> { + javadoc = SimpleTimeLimiter.create(Executors.newCachedThreadPool()).callWithTimeout(() -> { Reader reader; if (manager.getClientPreferences().isSupportsCompletionDocumentationMarkdown()) { reader = JavadocContentAccess2.getMarkdownContentReader(curMember); @@ -148,7 +149,7 @@ public CompletionItem resolve(CompletionItem param, IProgressMonitor monitor) { reader = JavadocContentAccess.getPlainTextContentReader(curMember); } return reader == null? null:CharStreams.toString(reader); - }, 500, TimeUnit.MILLISECONDS, true); + }, 500, TimeUnit.MILLISECONDS); } catch (UncheckedTimeoutException tooSlow) { //Ignore error for now as it's spamming clients on content assist. //TODO cache javadoc resolution results? diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/InitHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/InitHandler.java index 7286933e94..1206d49b02 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/InitHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/InitHandler.java @@ -218,9 +218,7 @@ InitializeResult initialize(InitializeParams param) { if (!preferenceManager.getClientPreferences().isSelectionRangeDynamicRegistered()) { capabilities.setSelectionRangeProvider(Boolean.TRUE); } - if (!preferenceManager.getClientPreferences().isCallHierarchyDynamicRegistered()) { - capabilities.setCallHierarchyProvider(Boolean.TRUE); - } + capabilities.setCallHierarchyProvider(Boolean.TRUE); TextDocumentSyncOptions textDocumentSyncOptions = new TextDocumentSyncOptions(); textDocumentSyncOptions.setOpenClose(Boolean.TRUE); textDocumentSyncOptions.setSave(new SaveOptions(Boolean.TRUE)); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java index 8a45147e66..f5261fec4f 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java @@ -74,8 +74,12 @@ import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager; import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager; import org.eclipse.jdt.ls.core.internal.preferences.Preferences; +import org.eclipse.lsp4j.CallHierarchyIncomingCall; +import org.eclipse.lsp4j.CallHierarchyIncomingCallsParams; import org.eclipse.lsp4j.CallHierarchyItem; -import org.eclipse.lsp4j.CallHierarchyParams; +import org.eclipse.lsp4j.CallHierarchyOutgoingCall; +import org.eclipse.lsp4j.CallHierarchyOutgoingCallsParams; +import org.eclipse.lsp4j.CallHierarchyPrepareParams; import org.eclipse.lsp4j.CodeAction; import org.eclipse.lsp4j.CodeActionKind; import org.eclipse.lsp4j.CodeActionOptions; @@ -119,7 +123,6 @@ import org.eclipse.lsp4j.RenameParams; import org.eclipse.lsp4j.SelectionRange; import org.eclipse.lsp4j.SelectionRangeParams; -import org.eclipse.lsp4j.ResolveCallHierarchyItemParams; import org.eclipse.lsp4j.SignatureHelp; import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.TextDocumentIdentifier; @@ -569,7 +572,7 @@ public CompletableFuture> references(ReferenceParams pa return computeAsync((monitor) -> handler.findReferences(params, monitor)); } - public CompletableFuture> findLinks(FindLinksParams params) { + public CompletableFuture> findLinks(FindLinksParams params) { logInfo(">> java/findLinks"); return computeAsync((monitor) -> FindLinksHandler.findLinks(params.type, params.position, monitor)); } @@ -907,22 +910,22 @@ public CompletableFuture> searchSymbols(SearchSymbolPara return computeAsyncWithClientProgress((monitor) -> WorkspaceSymbolHandler.search(params.getQuery(), params.maxResults, params.projectName, params.sourceOnly, monitor)); } - /* (non-Javadoc) - * @see org.eclipse.lsp4j.services.TextDocumentService#callHierarchy(org.eclipse.lsp4j.CallHierarchyParams) - */ @Override - public CompletableFuture callHierarchy(CallHierarchyParams params) { - logInfo(">> textDocumentt/callHierarchy"); - return computeAsyncWithClientProgress((monitor) -> new CallHierarchyHandler().callHierarchy(params, monitor)); + public CompletableFuture> prepareCallHierarchy(CallHierarchyPrepareParams params) { + logInfo(">> textDocumentt/prepareCallHierarchy"); + return computeAsyncWithClientProgress((monitor) -> new CallHierarchyHandler().prepareCallHierarchy(params, monitor)); + } + + @Override + public CompletableFuture> callHierarchyIncomingCalls(CallHierarchyIncomingCallsParams params) { + logInfo(">> callHierarchy/incomingCalls"); + return computeAsyncWithClientProgress((monitor) -> new CallHierarchyHandler().callHierarchyIncomingCalls(params, monitor)); } - /* (non-Javadoc) - * @see org.eclipse.lsp4j.services.TextDocumentService#resolveCallHierarchy(org.eclipse.lsp4j.ResolveCallHierarchyItemParams) - */ @Override - public CompletableFuture resolveCallHierarchy(ResolveCallHierarchyItemParams params) { - logInfo(">> callHierarchy/resolve"); - return computeAsyncWithClientProgress((monitor) -> new CallHierarchyResolveHandler().resolve(params, monitor)); + public CompletableFuture> callHierarchyOutgoingCalls(CallHierarchyOutgoingCallsParams params) { + logInfo(">> callHierarchy/outgoingCalls"); + return computeAsyncWithClientProgress((monitor) -> new CallHierarchyHandler().callHierarchyOutgoingCalls(params, monitor)); } public void sendStatus(ServiceStatus serverStatus, String status) { diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java index d6323bbe2c..c833da5985 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java @@ -287,7 +287,7 @@ public boolean isDiagnosticTagSupported() { //@formatter:off return v3supported && capabilities.getTextDocument().getPublishDiagnostics() != null && capabilities.getTextDocument().getPublishDiagnostics().getTagSupport() != null - && capabilities.getTextDocument().getPublishDiagnostics().getTagSupport().booleanValue(); + && capabilities.getTextDocument().getPublishDiagnostics().getTagSupport().getValueSet() != null; //@formatter:on } diff --git a/org.eclipse.jdt.ls.target/org.eclipse.jdt.ls.tp.target b/org.eclipse.jdt.ls.target/org.eclipse.jdt.ls.tp.target index 69e86d6bc9..39d1d34035 100644 --- a/org.eclipse.jdt.ls.target/org.eclipse.jdt.ls.tp.target +++ b/org.eclipse.jdt.ls.target/org.eclipse.jdt.ls.tp.target @@ -36,16 +36,16 @@ - + - - + + - + \ No newline at end of file diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyHandlerTest.java index 5f72b7b3bc..f5c4725d7c 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyHandlerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyHandlerTest.java @@ -10,10 +10,6 @@ *******************************************************************************/ package org.eclipse.jdt.ls.core.internal.handlers; -import static java.util.Arrays.asList; -import static java.util.stream.Collectors.toList; -import static org.eclipse.lsp4j.CallHierarchyDirection.Incoming; -import static org.eclipse.lsp4j.CallHierarchyDirection.Outgoing; import static org.eclipse.lsp4j.SymbolKind.Class; import static org.eclipse.lsp4j.SymbolKind.Constructor; import static org.eclipse.lsp4j.SymbolKind.Field; @@ -25,6 +21,7 @@ import java.util.Arrays; import java.util.List; +import java.util.stream.Stream; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jdt.core.JavaModelException; @@ -32,12 +29,15 @@ import org.eclipse.jdt.ls.core.internal.WorkspaceHelper; import org.eclipse.jdt.ls.core.internal.hover.JavaElementLabels; import org.eclipse.jdt.ls.core.internal.managers.AbstractProjectsManagerBasedTest; -import org.eclipse.lsp4j.CallHierarchyDirection; +import org.eclipse.lsp4j.CallHierarchyIncomingCall; +import org.eclipse.lsp4j.CallHierarchyIncomingCallsParams; import org.eclipse.lsp4j.CallHierarchyItem; -import org.eclipse.lsp4j.CallHierarchyParams; -import org.eclipse.lsp4j.Location; +import org.eclipse.lsp4j.CallHierarchyOutgoingCall; +import org.eclipse.lsp4j.CallHierarchyOutgoingCallsParams; +import org.eclipse.lsp4j.CallHierarchyPrepareParams; import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.SymbolKind; +import org.eclipse.lsp4j.SymbolTag; import org.eclipse.lsp4j.TextDocumentIdentifier; import org.junit.Before; import org.junit.Test; @@ -53,92 +53,118 @@ public void setup() throws Exception { } @Test - public void incoming_src_missing() throws Exception { + public void prepareCallHierarchy_noItemAtLocation() throws Exception { // Line 16 from `CallHierarchy` //<|>/*nothing*/ String uri = getUriFromSrcProject("org.sample.CallHierarchy"); - assertNull(getIncomings(uri, 13, 0, 1)); + assertNull(prepareCallHierarchy(uri, 15, 0)); } @Test - public void incoming_src_resolve_0() throws Exception { + public void prepareCallHierarchy() throws Exception { // Line 15 from `CallHierarchy` // protected int <|>protectedField = 200; String uri = getUriFromSrcProject("org.sample.CallHierarchy"); - CallHierarchyItem item = getIncomings(uri, 14, 18, 0); - assertItem(item, "protectedField", Field, "", null, false, null); + List items = prepareCallHierarchy(uri, 14, 18); + assertNotNull(items); + assertEquals(1, items.size()); + assertItem(items.get(0), "protectedField", Field, "", false, 14); } @Test - public void incoming_src_resolve_1() throws Exception { - // Line 26 from `CallHierarchy` - // public void <|>bar() { + public void prepareCallHierarchy_src_enclosing() throws Exception { + // Line 20 from `CallHierarchy` + ///*should resolve to enclosing "method/constructor/initializer"*/ String uri = getUriFromSrcProject("org.sample.CallHierarchy"); - CallHierarchyItem item = getIncomings(uri, 25, 16, 1); - assertItem(item, "bar()", Method, "void", 3, false, null); - - List calls = item.getCalls(); - assertItem(calls.get(0), "Child()", Constructor, "", null, false, asList(45)); - assertItem(calls.get(1), "main(String[])", Method, "void", null, true, asList(7)); - assertItem(calls.get(2), "method_1()", Method, "void", null, false, asList(35)); + List items = prepareCallHierarchy(uri, 19, 0); + assertNotNull(items); + assertEquals(1, items.size()); + assertItem(items.get(0), "Base()", Constructor, "", false, 18); } @Test - public void outgoing_src_resolve_0_enclosing() throws Exception { - // Line 20 from `CallHierarchy` - ///*should resolve to enclosing "method/constructor/initializer"*/ + public void incomingCalls_src() throws Exception { + // Line 27 from `CallHierarchy` + // public void <|>bar() { String uri = getUriFromSrcProject("org.sample.CallHierarchy"); - CallHierarchyItem item = getIncomings(uri, 19, 0, 0); - assertItem(item, "Base()", Constructor, "", null, false, null); + List items = prepareCallHierarchy(uri, 26, 16); + assertNotNull(items); + assertEquals(1, items.size()); + assertItem(items.get(0), "bar()", Method, "void", false, 26); + + List calls = getIncomingCalls(items.get(0)); + assertNotNull(calls); + assertEquals(3, calls.size()); + assertItem(calls.get(0).getFrom(), "Child()", Constructor, "", false, 42); + assertItem(calls.get(1).getFrom(), "main(String[])", Method, "void", true, 5); + assertItem(calls.get(2).getFrom(), "method_1()", Method, "void", false, 33); } @Test - public void outgoing_src_resolve_2() throws Exception { + public void outgoingCalls_src() throws Exception { // Line 34 from `CallHierarchy` // protected void <|>method_1() { String uri = getUriFromSrcProject("org.sample.CallHierarchy"); - CallHierarchyItem item = getOutgoings(uri, 33, 19, 2); - assertItem(item, "method_1()", Method, "void", 2, false, null); - - List calls = item.getCalls(); - assertItem(calls.get(0), "foo()", Method, "void", 0, false, asList(34)); - assertItem(calls.get(1), "bar()", Method, "void", 2, false, asList(35)); - - List call1Calls = calls.get(1).getCalls(); - assertItem(call1Calls.get(0), "Child()", Constructor, "", null, false, asList(27, 28)); - assertItem(call1Calls.get(1), "currentThread()", Method, "Thread", null, false, asList(29, 30)); + List items = prepareCallHierarchy(uri, 33, 19); + assertNotNull(items); + assertEquals(1, items.size()); + assertItem(items.get(0), "method_1()", Method, "void", false, 33); + + List calls = getOutgoings(items.get(0)); + assertNotNull(calls); + assertEquals(2, calls.size()); + assertItem(calls.get(0).getTo(), "foo()", Method, "void", false, 22); + assertItem(calls.get(1).getTo(), "bar()", Method, "void", false, 26); + + List call1Calls = getOutgoings(calls.get(1).getTo()); + assertNotNull(call1Calls); + assertEquals(2, call1Calls.size()); + assertItem(call1Calls.get(0).getTo(), "Child()", Constructor, "", false, 42); + assertItem(call1Calls.get(1).getTo(), "currentThread()", Method, "Thread", false, 0); } @Test - public void incoming_jar_resolve_2() throws Exception { + public void incomingCalls_maven() throws Exception { // Line 12 from `CallHierarchyOther` // @Deprecated public static class <|>X { String uri = getUriFromJarProject("org.sample.CallHierarchyOther"); - CallHierarchyItem item = getIncomings(uri, 11, 34, 2); - assertItem(item, "X", Class, "", 1, true, null); - - List calls = item.getCalls(); - assertItem(calls.get(0), "FooBuilder()", Constructor, "", 1, false, asList(10)); - - List call0Calls = calls.get(0).getCalls(); - assertItem(call0Calls.get(0), "{...}", Constructor, "", null, false, asList(5, 6, 7)); + List items = prepareCallHierarchy(uri, 11, 34); + assertNotNull(items); + assertEquals(1, items.size()); + assertItem(items.get(0), "X", Class, "", true, 11); + + List calls = getIncomingCalls(items.get(0)); + assertNotNull(calls); + assertEquals(1, calls.size()); + assertItem(calls.get(0).getFrom(), "FooBuilder()", Constructor, "", false, 9); + + List call0Calls = getIncomingCalls(calls.get(0).getFrom()); + assertNotNull(call0Calls); + assertEquals(1, call0Calls.size()); + assertItem(call0Calls.get(0).getFrom(), "{...}", Constructor, "", false, 4); } @Test - public void outgoing_jar_resolve_2() throws Exception { + public void outgoing_jar() throws Exception { // Line 15 from `CallHierarchy` // public Object <|>build() { String uri = getUriFromJarProject("org.sample.CallHierarchy"); - CallHierarchyItem item = getOutgoings(uri, 14, 18, 2); - assertItem(item, "build()", Method, "Object", 1, false, null); - - List calls = item.getCalls(); - assertItem(calls.get(0), "capitalize(String)", Method, "String", 1, false, asList(15, 16)); - - List call0Calls = calls.get(0).getCalls(); - assertItem(call0Calls.get(0), "capitalize(String, char...)", Method, "String", null, false, asList(369)); - - String jarUri = call0Calls.get(0).getUri(); + List items = prepareCallHierarchy(uri, 14, 18); + assertNotNull(items); + assertEquals(1, items.size()); + assertItem(items.get(0), "build()", Method, "Object", false, 14); + + List calls = getOutgoings(items.get(0)); + assertNotNull(calls); + assertEquals(1, calls.size()); + assertItem(calls.get(0).getTo(), "capitalize(String)", Method, "String", false, 368); + + List call0Calls = getOutgoings(calls.get(0).getTo()); + assertNotNull(call0Calls); + assertEquals(1, call0Calls.size()); + assertItem(call0Calls.get(0).getTo(), "capitalize(String, char...)", Method, "String", false, 401); + + String jarUri = call0Calls.get(0).getTo().getUri(); assertTrue(jarUri.startsWith("jdt://")); assertTrue(jarUri.contains("org.apache.commons.lang3.text")); assertTrue(jarUri.contains("WordUtils.class")); @@ -153,16 +179,13 @@ public void outgoing_jar_resolve_2() throws Exception { * the expected kind * @param detail * the expected detail without the ` : ` (declaration) suffix. - * @param calls - * the number of calls or {@code null} if expected non-defined calls. * @param deprecated * expected deprecated state - * @param callLocationStartLines - * {@code null}, if there are no call locations. Otherwise a list of - * expected start lines for the call locations + * @param selectionStartLine + * the start line of the selection range * @return the {@code item} */ - static CallHierarchyItem assertItem(CallHierarchyItem item, String name, SymbolKind kind, String detail, Integer calls, boolean deprecated, List callLocationStartLines) { + static CallHierarchyItem assertItem(CallHierarchyItem item, String name, SymbolKind kind, String detail, boolean deprecated, int selectionStartLine) { assertNotNull(item); assertEquals(name, item.getName()); assertEquals(kind, item.getKind()); @@ -171,39 +194,38 @@ static CallHierarchyItem assertItem(CallHierarchyItem item, String name, SymbolK } else { assertEquals(JavaElementLabels.DECL_STRING + detail, item.getDetail()); } - if (calls == null) { - assertNull(item.getCalls()); + if (deprecated) { + assertNotNull(item.getTags()); + assertTrue(Stream.of(item.getTags()).anyMatch(tag -> tag == SymbolTag.Deprecated)); } else { - assertEquals(calls.intValue(), item.getCalls().size()); - } - assertEquals(deprecated, item.getDeprecated()); - if (callLocationStartLines == null) { - assertNull(item.getCallLocations()); - } else { - List callLocations = item.getCallLocations(); - assertEquals(callLocationStartLines.size(), callLocations.size()); - List actualStartLines = callLocations.stream().map(loc -> loc.getRange().getStart().getLine()).collect(toList()); - assertEquals(callLocationStartLines, actualStartLines); + assertTrue(item.getTags() == null || item.getTags().length == 0 || !Stream.of(item.getTags()).anyMatch(tag -> tag == SymbolTag.Deprecated)); } + + assertEquals(selectionStartLine, item.getSelectionRange().getStart().getLine()); return item; } - static CallHierarchyItem getIncomings(String uri, int line, int character, int resolve) { - CallHierarchyParams params = createParams(uri, line, character, Incoming, resolve); - return new CallHierarchyHandler().callHierarchy(params, new NullProgressMonitor()); + static List prepareCallHierarchy(String uri, int line, int character) { + CallHierarchyPrepareParams params = createCallHierarchyPrepareParams(uri, line, character); + return new CallHierarchyHandler().prepareCallHierarchy(params, new NullProgressMonitor()); + } + + static List getIncomingCalls(CallHierarchyItem item) { + CallHierarchyIncomingCallsParams params = new CallHierarchyIncomingCallsParams(); + params.setItem(item); + return new CallHierarchyHandler().callHierarchyIncomingCalls(params, new NullProgressMonitor()); } - static CallHierarchyItem getOutgoings(String uri, int line, int character, int resolve) { - CallHierarchyParams params = createParams(uri, line, character, Outgoing, resolve); - return new CallHierarchyHandler().callHierarchy(params, new NullProgressMonitor()); + static List getOutgoings(CallHierarchyItem item) { + CallHierarchyOutgoingCallsParams params = new CallHierarchyOutgoingCallsParams(); + params.setItem(item); + return new CallHierarchyHandler().callHierarchyOutgoingCalls(params, new NullProgressMonitor()); } - static CallHierarchyParams createParams(String uri, int line, int character, CallHierarchyDirection direction, int resolve) { - CallHierarchyParams params = new CallHierarchyParams(); + static CallHierarchyPrepareParams createCallHierarchyPrepareParams(String uri, int line, int character) { + CallHierarchyPrepareParams params = new CallHierarchyPrepareParams(); params.setTextDocument(new TextDocumentIdentifier(uri)); params.setPosition(new Position(line, character)); - params.setDirection(direction); - params.setResolve(resolve); return params; } diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyResolveHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyResolveHandlerTest.java deleted file mode 100644 index d312ce4180..0000000000 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyResolveHandlerTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 TypeFox and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * TypeFox - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.handlers; - -import static java.util.Arrays.asList; -import static org.eclipse.jdt.ls.core.internal.handlers.CallHierarchyHandlerTest.assertItem; -import static org.eclipse.jdt.ls.core.internal.handlers.CallHierarchyHandlerTest.getIncomings; -import static org.eclipse.jdt.ls.core.internal.handlers.CallHierarchyHandlerTest.getUriFromSrcProject; -import static org.eclipse.lsp4j.SymbolKind.Constructor; -import static org.eclipse.lsp4j.SymbolKind.Method; -import static org.junit.Assert.assertNull; - -import java.util.Arrays; -import java.util.List; - -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jdt.ls.core.internal.managers.AbstractProjectsManagerBasedTest; -import org.eclipse.lsp4j.CallHierarchyDirection; -import org.eclipse.lsp4j.CallHierarchyItem; -import org.eclipse.lsp4j.Position; -import org.eclipse.lsp4j.Range; -import org.eclipse.lsp4j.ResolveCallHierarchyItemParams; -import org.junit.Before; -import org.junit.Test; - -/** - * @see CallHierarchyResolveHandler - */ -public class CallHierarchyResolveHandlerTest extends AbstractProjectsManagerBasedTest { - - @Before - public void setup() throws Exception { - importProjects(Arrays.asList("eclipse/hello", "maven/salut")); - } - - @Test - public void cannot_resolve() { - CallHierarchyItem invalid = new CallHierarchyItem(); - invalid.setUri("file:///missing/Resource.java"); - invalid.setRange(new Range(new Position(0, 0), new Position(0, 0))); - CallHierarchyItem item = resolveIncoming(invalid, 1); - assertNull(item); - } - - @Test - public void resolve_incoming() throws Exception { - // Line 26 from `CallHierarchy` - // public void <|>bar() { - String uri = getUriFromSrcProject("org.sample.CallHierarchy"); - CallHierarchyItem item = getIncomings(uri, 25, 16, 0); - assertItem(item, "bar()", Method, "void", null, false, null); - - item = resolveIncoming(item, 1); - assertItem(item, "bar()", Method, "void", 3, false, null); - - List calls = item.getCalls(); - assertItem(calls.get(0), "Child()", Constructor, "", null, false, asList(45)); - assertItem(calls.get(1), "main(String[])", Method, "void", null, true, asList(7)); - assertItem(calls.get(2), "method_1()", Method, "void", null, false, asList(35)); - } - - private static CallHierarchyItem resolveIncoming(CallHierarchyItem toResolve, int resolve) { - ResolveCallHierarchyItemParams params = new ResolveCallHierarchyItemParams(); - params.setDirection(CallHierarchyDirection.Incoming); - params.setItem(toResolve); - params.setResolve(resolve); - return new CallHierarchyResolveHandler().resolve(params, new NullProgressMonitor()); - } - -}