Skip to content

Commit

Permalink
GH-508: Added support for call hierarchies.
Browse files Browse the repository at this point in the history
Closes #508

Signed-off-by: Akos Kitta <[email protected]>
  • Loading branch information
Akos Kitta authored and fbricon committed Dec 18, 2019
1 parent f1647bc commit 2fe81cb
Show file tree
Hide file tree
Showing 18 changed files with 969 additions and 13 deletions.
1 change: 1 addition & 0 deletions org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Export-Package: org.eclipse.jdt.ls.core.internal;x-friends:="org.eclipse.jdt.ls.
org.eclipse.jdt.ls.core.internal.corrections.proposals;x-internal:=true,
org.eclipse.jdt.ls.core.internal.handlers;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.jdt.ls.core.internal.highlighting;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.jdt.ls.core.internal.hover;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.jdt.ls.core.internal.javadoc;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.jdt.ls.core.internal.lsp;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.jdt.ls.core.internal.managers;x-friends:="org.eclipse.jdt.ls.tests",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
package org.eclipse.jdt.ls.core.internal;

import static org.eclipse.core.resources.IResource.DEPTH_ONE;
import static org.eclipse.jdt.ls.core.internal.hover.JavaElementLabels.ALL_DEFAULT;
import static org.eclipse.jdt.ls.core.internal.hover.JavaElementLabels.M_APP_RETURNTYPE;
import static org.eclipse.jdt.ls.core.internal.hover.JavaElementLabels.ROOT_VARIABLE;

import java.io.File;
import java.io.IOException;
Expand All @@ -32,6 +35,7 @@
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
Expand All @@ -41,6 +45,7 @@
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.jdt.core.CompletionProposal;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IAnnotatable;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IBuffer;
Expand Down Expand Up @@ -104,6 +109,7 @@
import org.eclipse.jdt.ls.core.internal.hover.JavaElementLabelComposer;
import org.eclipse.jdt.ls.core.internal.hover.JavaElementLabels;
import org.eclipse.jdt.ls.core.internal.javadoc.JavaElementLinks;
import org.eclipse.jdt.ls.core.internal.hover.JavaElementLabels;
import org.eclipse.jdt.ls.core.internal.managers.ContentProviderManager;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
Expand All @@ -114,6 +120,7 @@
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.SymbolKind;

import com.google.common.base.Charsets;
import com.google.common.io.Files;
Expand Down Expand Up @@ -306,14 +313,109 @@ public static String getPackageName(IJavaProject javaProject, String fileContent
return (pkg == null || pkg.getName() == null)?"":pkg.getName().getFullyQualifiedName();
}

/**
* Returns with the human readable name of the element. For types with type
* arguments, it is {@code Comparable<T>} instead of {@code Comparable}. First,
* this method tries to retrieve the
* {@link JavaElementLabels#getElementLabel(IJavaElement, long) label} of the
* element, then falls back to {@link IJavaElement#getElementName() element
* name}. Returns {@code null} if the argument does not have a name.
*/
public static String getName(IJavaElement element) {
Assert.isNotNull(element, "element");
String name = JavaElementLabels.getElementLabel(element, ALL_DEFAULT);
return name == null ? element.getElementName() : name;
}

/**
* Given the uri returns a {@link IClassFile}.
* May return null if it can not resolve the uri to a
* library.
* Returns with the details of the document symbol. This is usually the type
* information of a member. For methods, this is the type information of the
* return type. Can return with an empty string, but never {@code null}.
*
* @see JDTUtils#getName(IJavaElement)
*/
public static String getDetail(IJavaElement element) {
Assert.isNotNull(element, "element");
String name = getName(element);
String nameWithDetails = JavaElementLabels.getElementLabel(element, ALL_DEFAULT | M_APP_RETURNTYPE | ROOT_VARIABLE);
if (nameWithDetails != null && nameWithDetails.startsWith(name)) {
return nameWithDetails.substring(name.length());
}
return "";
}

/**
* Returns with the document symbol {@code SymbolKind kind} for the Java
* element.
*/
public static SymbolKind getSymbolKind(IJavaElement element) {
switch (element.getElementType()) {
case IJavaElement.ANNOTATION:
return SymbolKind.Property; // TODO: find a better mapping
case IJavaElement.CLASS_FILE:
case IJavaElement.COMPILATION_UNIT:
return SymbolKind.File;
case IJavaElement.FIELD:
return SymbolKind.Field;
case IJavaElement.IMPORT_CONTAINER:
case IJavaElement.IMPORT_DECLARATION:
return SymbolKind.Module;
case IJavaElement.INITIALIZER:
return SymbolKind.Constructor;
case IJavaElement.LOCAL_VARIABLE:
case IJavaElement.TYPE_PARAMETER:
return SymbolKind.Variable;
case IJavaElement.METHOD:
try {
// TODO handle `IInitializer`. What should be the `SymbolKind`?
if (element instanceof IMethod) {
if (((IMethod) element).isConstructor()) {
return SymbolKind.Constructor;
}
}
return SymbolKind.Method;
} catch (JavaModelException e) {
return SymbolKind.Method;
}
case IJavaElement.PACKAGE_DECLARATION:
return SymbolKind.Package;
case IJavaElement.TYPE:
try {
IType type = (IType) element;
if (type.isEnum()) {
return SymbolKind.Enum;
} else if (type.isInterface()) {
return SymbolKind.Interface;
} else {
return SymbolKind.Class;
}
} catch (JavaModelException e) {
return SymbolKind.Class;
}
}
return SymbolKind.String;
}

/**
* {@code true} if the element is deprecated. Otherwise, {@code false}.
*/
public static boolean isDeprecated(IJavaElement element) throws JavaModelException {
Assert.isNotNull(element, "element");
if (element instanceof ITypeRoot) {
return Flags.isDeprecated(((ITypeRoot) element).findPrimaryType().getFlags());
} else if (element instanceof IMember) {
return Flags.isDeprecated(((IMember) element).getFlags());
}
return false;
}

/**
* Given the uri returns a {@link IClassFile}. May return null if it can not
* resolve the uri to a library.
*
* @see #toLocation(IClassFile, int, int)
* @param uri with 'jdt' scheme
* @param uri
* with 'jdt' scheme
* @return class file
*/
public static IClassFile resolveClassFile(String uriString){
Expand Down Expand Up @@ -388,6 +490,13 @@ ISourceRange getRange(IJavaElement element) throws JavaModelException {
};

/* default */ abstract ISourceRange getRange(IJavaElement element) throws JavaModelException;

/**
* Sugar for {@link JDTUtils#toLocation(IJavaElement, LocationType)}.
*/
public Location toLocation(IJavaElement element) throws JavaModelException {
return JDTUtils.toLocation(element, this);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
import org.osgi.framework.BundleException;
import org.osgi.util.tracker.ServiceTracker;

import com.google.common.base.Throwables;

public class JavaLanguageServerPlugin extends Plugin {

private static final String JDT_UI_PLUGIN = "org.eclipse.jdt.ui";
Expand Down Expand Up @@ -377,6 +379,16 @@ public static void logInfo(String message) {
}
}

public static void logException(Throwable ex) {
if (context != null) {
String message = ex.getMessage();
if (message == null) {
message = Throwables.getStackTraceAsString(ex);
}
logException(message, ex);
}
}

public static void logException(String message, Throwable ex) {
if (context != null) {
log(new Status(IStatus.ERROR, context.getBundle().getSymbolicName(), message, ex));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class CallHierarchy {
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 = "java.*,javax.*"; //$NON-NLS-1$
private static final String DEFAULT_IGNORE_FILTERS = ""; //$NON-NLS-1$
private static CallHierarchy fgInstance;
private IJavaSearchScope fSearchScope;
private StringMatcher[] fFilters;
Expand Down
Loading

0 comments on commit 2fe81cb

Please sign in to comment.