Skip to content

Commit

Permalink
change the handlers
Browse files Browse the repository at this point in the history
Signed-off-by: Shi Chen <[email protected]>
  • Loading branch information
CsCherrYY committed Mar 27, 2023
1 parent 57a73be commit edfab69
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 228 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal.commands;
package org.eclipse.jdt.ls.core.internal.handlers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -35,89 +37,150 @@
import org.eclipse.jdt.ls.core.internal.JDTUtils.LocationType;
import org.eclipse.jdt.ls.core.internal.JSONUtility;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.handlers.DocumentSymbolHandler;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.SymbolKind;
import org.eclipse.lsp4j.SymbolTag;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.legacy.typeHierarchy.ResolveTypeHierarchyItemParams;
import org.eclipse.lsp4j.legacy.typeHierarchy.TypeHierarchyDirection;
import org.eclipse.lsp4j.legacy.typeHierarchy.TypeHierarchyItem;
import org.eclipse.lsp4j.legacy.typeHierarchy.TypeHierarchyParams;
import org.eclipse.lsp4j.TypeHierarchyItem;
import org.eclipse.lsp4j.TypeHierarchyPrepareParams;
import org.eclipse.lsp4j.TypeHierarchySubtypesParams;
import org.eclipse.lsp4j.TypeHierarchySupertypesParams;

public class TypeHierarchyCommand {
public class TypeHierarchyHandler {

public TypeHierarchyItem typeHierarchy(TypeHierarchyParams params, IProgressMonitor monitor) {
public enum TypeHierarchyDirection {
Subtype, Supertype;
}

private static class TypeHierarchyItemData {
private String handleIdentifier;
private String methodIdentifier;
private String methodName;

public TypeHierarchyItemData(String handleIdentifier, String methodIdentifier, String methodName) {
this.handleIdentifier = handleIdentifier;
this.methodIdentifier = methodIdentifier;
this.methodName = methodName;
}

private static TypeHierarchyItemData getTypeHierarchyItemData(Object data) {
if (data == null) {
return null;
}
Map<String, String> map = JSONUtility.toModel(data, Map.class);
String handleIdentifier = map.get("element");
String methodIdentifier = map.get("method");
String methodName = map.get("method_name");
return new TypeHierarchyItemData(handleIdentifier, methodIdentifier, methodName);
}
}

public List<TypeHierarchyItem> prepareTypeHierarchy(TypeHierarchyPrepareParams params, IProgressMonitor monitor) {
if (params == null) {
return null;
return Collections.emptyList();
}
TextDocumentIdentifier textDocument = params.getTextDocument();
if (textDocument == null) {
return null;
return Collections.emptyList();
}
Position position = params.getPosition();
String uri = textDocument.getUri();
TypeHierarchyDirection direction = params.getDirection();
int resolve = params.getResolve();
return getTypeHierarchy(uri, position, direction, resolve, null, monitor);
return getTypeHierarchyItems(uri, position, monitor);
}

public TypeHierarchyItem resolveTypeHierarchy(ResolveTypeHierarchyItemParams params, IProgressMonitor monitor) {
if (params == null) {
return null;
private List<TypeHierarchyItem> getTypeHierarchyItems(String uri, Position position, IProgressMonitor monitor) {
if (uri == null || position == null) {
return Collections.emptyList();
}
TypeHierarchyItem item = params.getItem();
if (item == null) {
return null;
try {
IMember member = getMember(uri, position, monitor);
IMethod targetMethod = null;
if (member instanceof IMethod) {
targetMethod = (IMethod) member;
}
TypeHierarchyItem item = targetMethod == null ? TypeHierarchyHandler.toTypeHierarchyItem(member) : TypeHierarchyHandler.toTypeHierarchyItem(member, false, targetMethod);
if (item == null) {
return Collections.emptyList();
}
return Arrays.asList(item);
} catch (JavaModelException e) {
return Collections.emptyList();
}
Range range = item.getRange();
if (range == null) {
return null;
}

public List<TypeHierarchyItem> getSupertypeItems(TypeHierarchySupertypesParams params, IProgressMonitor monitor) {
return getTypeHierarchyItems(params.getItem(), TypeHierarchyDirection.Supertype, monitor);
}

public List<TypeHierarchyItem> getSubtypeItems(TypeHierarchySubtypesParams params, IProgressMonitor monitor) {
return getTypeHierarchyItems(params.getItem(), TypeHierarchyDirection.Subtype, monitor);
}

private List<TypeHierarchyItem> getTypeHierarchyItems(TypeHierarchyItem item, TypeHierarchyDirection direction, IProgressMonitor monitor) {
TypeHierarchyItemData data = TypeHierarchyItemData.getTypeHierarchyItemData(item.getData());
if (data == null) {
return Collections.emptyList();
}
Position position = range.getStart();
String uri = item.getUri();
TypeHierarchyDirection direction = params.getDirection();
int resolve = params.getResolve();
return getTypeHierarchy(uri, position, direction, resolve, item, monitor);
IJavaElement element = JavaCore.create(data.handleIdentifier);
IMember member = null;
IMethod targetMethod = null;
if (data.methodIdentifier != null) {
targetMethod = (IMethod) JavaCore.create(data.methodIdentifier);
}
if (element instanceof IType || element instanceof IMethod) {
member = (IMember) element;
} else if (element instanceof IOrdinaryClassFile classFile) {
member = classFile.getType();
} else {
return Collections.emptyList();
}
return resolveTypeHierarchyItems(member, targetMethod, direction, monitor);
}

private TypeHierarchyItem getTypeHierarchy(String uri, Position position, TypeHierarchyDirection direction, int resolve, TypeHierarchyItem itemInput, IProgressMonitor monitor) {
if (uri == null || position == null || direction == null) {
return null;
private List<TypeHierarchyItem> resolveTypeHierarchyItems(IMember member, IMethod targetMethod, TypeHierarchyDirection direction, IProgressMonitor monitor) {
if (monitor.isCanceled()) {
return Collections.emptyList();
}
IType type = null;
if (member instanceof IType) {
type = (IType) member;
} else {
type = member.getDeclaringType();
}
try {
IMember member = null;
IMethod targetMethod = null;
if (itemInput == null) {
member = getMember(uri, position, monitor);
if (member instanceof IMethod) {
targetMethod = (IMethod) member;
}
ITypeHierarchy typeHierarchy = null;
List<TypeHierarchyItem> items = new ArrayList<>();
IType[] hierarchyTypes = null;
if (direction == TypeHierarchyDirection.Supertype) {
typeHierarchy = type.newSupertypeHierarchy(DefaultWorkingCopyOwner.PRIMARY, monitor);
hierarchyTypes = typeHierarchy.getSupertypes(type);
} else {
Map<String, String> data = JSONUtility.toModel(itemInput.getData(), Map.class);
String handleIdentifier = data.get("element");
IJavaElement element = JavaCore.create(handleIdentifier);
String methodIdentifier = data.get("method");
if (methodIdentifier != null) {
targetMethod = (IMethod) JavaCore.create(methodIdentifier);
}
if (element instanceof IType || element instanceof IMethod) {
member = (IMember) element;
} else if (element instanceof IOrdinaryClassFile classFile) {
member = classFile.getType();
ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, true);
typeHierarchy = type.newTypeHierarchy(workingCopies, monitor);
hierarchyTypes = typeHierarchy.getSubtypes(type);
}
for (IType hierarchyType : hierarchyTypes) {
TypeHierarchyItem item = null;
if (targetMethod != null) {
IMethod[] matches = hierarchyType.findMethods(targetMethod);
boolean excludeMember = matches == null || matches.length == 0;
// Do not show java.lang.Object unless target method is based there
if (!excludeMember || !"java.lang.Object".equals(hierarchyType.getFullyQualifiedName())) {
item = TypeHierarchyHandler.toTypeHierarchyItem(excludeMember ? hierarchyType : matches[0], excludeMember, targetMethod);
}
} else {
return null;
item = TypeHierarchyHandler.toTypeHierarchyItem(hierarchyType);
}
if (item == null) {
continue;
}
items.add(item);
}
TypeHierarchyItem item = TypeHierarchyCommand.toTypeHierarchyItem(member);
if (item == null) {
return null;
}
resolve(item, member, targetMethod, direction, resolve, monitor);
return item;
return items;
} catch (JavaModelException e) {
return null;
return Collections.emptyList();
}
}

Expand Down Expand Up @@ -160,10 +223,10 @@ private static TypeHierarchyItem toTypeHierarchyItem(IMember member, boolean exc
if (location == null || selectLocation == null) {
return null;
}
TypeHierarchyItem item = new TypeHierarchyItem();
item.setRange(location.getRange());
item.setUri(location.getUri());
item.setSelectionRange(selectLocation.getRange());

Range range = location.getRange();
String uri = location.getUri();
Range selectionRange = selectLocation.getRange();

IType type = null;
if (member instanceof IType) {
Expand All @@ -172,20 +235,25 @@ private static TypeHierarchyItem toTypeHierarchyItem(IMember member, boolean exc
type = member.getDeclaringType();
}

String name = null;
String detail = null;
String fullyQualifiedName = type.getFullyQualifiedName();
int index = fullyQualifiedName.lastIndexOf('.');
if (index >= 1 && index < fullyQualifiedName.length() - 1 && !type.isAnonymous()) {
item.setName(fullyQualifiedName.substring(index + 1));
item.setDetail(fullyQualifiedName.substring(0, index));
name = fullyQualifiedName.substring(index + 1);
detail = fullyQualifiedName.substring(0, index);
} else {
item.setName(JDTUtils.getName(type));
name = JDTUtils.getName(type);
IPackageFragment packageFragment = type.getPackageFragment();
if (packageFragment != null) {
item.setDetail(packageFragment.getElementName());
detail = packageFragment.getElementName();
}
}
item.setKind(excludeMember ? SymbolKind.Null : DocumentSymbolHandler.mapKind(type));
item.setDeprecated(JDTUtils.isDeprecated(member));
SymbolKind kind = excludeMember ? SymbolKind.Null : DocumentSymbolHandler.mapKind(type);
List<SymbolTag> tags = new ArrayList<>();
if (JDTUtils.isDeprecated(member)) {
tags.add(SymbolTag.Deprecated);
}
Map<String, String> data = new HashMap<>();
data.put("element", member.getHandleIdentifier());
if (targetMethod != null) {
Expand All @@ -195,6 +263,8 @@ private static TypeHierarchyItem toTypeHierarchyItem(IMember member, boolean exc
data.put("method", member.getHandleIdentifier());
data.put("method_name", member.getElementName());
}
TypeHierarchyItem item = new TypeHierarchyItem(name, kind, uri, range, selectionRange, detail);
item.setTags(tags);
item.setData(data);
return item;
}
Expand All @@ -206,68 +276,4 @@ private static Location getLocation(IMember member, LocationType locationType) t
}
return location;
}

private void resolve(TypeHierarchyItem item, IMember member, IMethod targetMethod, TypeHierarchyDirection direction, int resolve, IProgressMonitor monitor) throws JavaModelException {
if (monitor.isCanceled() || resolve <= 0) {
return;
}

IType type = null;
if (member instanceof IType) {
type = (IType) member;
} else {
type = member.getDeclaringType();
}

ITypeHierarchy typeHierarchy;
if (direction == TypeHierarchyDirection.Parents) {
typeHierarchy = type.newSupertypeHierarchy(DefaultWorkingCopyOwner.PRIMARY, monitor);
} else {
ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, true);
typeHierarchy = type.newTypeHierarchy(workingCopies, monitor);
}
if (direction == TypeHierarchyDirection.Children || direction == TypeHierarchyDirection.Both) {
List<TypeHierarchyItem> childrenItems = new ArrayList<>();
IType[] children = typeHierarchy.getSubtypes(type);
for (IType childType : children) {
TypeHierarchyItem childItem = null;
if (targetMethod != null) {
IMethod[] matches = childType.findMethods(targetMethod);
boolean excludeMember = matches == null || matches.length == 0;
childItem = TypeHierarchyCommand.toTypeHierarchyItem(excludeMember ? childType : matches[0], excludeMember, targetMethod);
} else {
childItem = TypeHierarchyCommand.toTypeHierarchyItem(childType);
}
if (childItem == null) {
continue;
}
resolve(childItem, childType, targetMethod, direction, resolve - 1, monitor);
childrenItems.add(childItem);
}
item.setChildren(childrenItems);
}
if (direction == TypeHierarchyDirection.Parents || direction == TypeHierarchyDirection.Both) {
List<TypeHierarchyItem> parentsItems = new ArrayList<>();
IType[] parents = typeHierarchy.getSupertypes(type);
for (IType parentType : parents) {
TypeHierarchyItem parentItem = null;
if (targetMethod != null) {
IMethod[] matches = parentType.findMethods(targetMethod);
boolean excludeMember = matches == null || matches.length == 0;
// Do not show java.lang.Object unless target method is based there
if (!excludeMember || !"java.lang.Object".equals(parentType.getFullyQualifiedName())) {
parentItem = TypeHierarchyCommand.toTypeHierarchyItem(excludeMember ? parentType : matches[0], excludeMember, targetMethod);
}
} else {
parentItem = TypeHierarchyCommand.toTypeHierarchyItem(parentType);
}
if (parentItem == null) {
continue;
}
resolve(parentItem, parentType, targetMethod, direction, resolve - 1, monitor);
parentsItems.add(parentItem);
}
item.setParents(parentsItems);
}
}
}
Loading

0 comments on commit edfab69

Please sign in to comment.