1010 * Contributors:
1111 * Microsoft Corporation - initial API and implementation
1212*******************************************************************************/
13- package org .eclipse .jdt .ls .core .internal .commands ;
13+ package org .eclipse .jdt .ls .core .internal .handlers ;
1414
1515import java .util .ArrayList ;
16+ import java .util .Arrays ;
17+ import java .util .Collections ;
1618import java .util .HashMap ;
1719import java .util .List ;
1820import java .util .Map ;
3537import org .eclipse .jdt .ls .core .internal .JDTUtils .LocationType ;
3638import org .eclipse .jdt .ls .core .internal .JSONUtility ;
3739import org .eclipse .jdt .ls .core .internal .JavaLanguageServerPlugin ;
38- import org .eclipse .jdt .ls .core .internal .handlers .DocumentSymbolHandler ;
3940import org .eclipse .lsp4j .Location ;
4041import org .eclipse .lsp4j .Position ;
4142import org .eclipse .lsp4j .Range ;
4243import org .eclipse .lsp4j .SymbolKind ;
44+ import org .eclipse .lsp4j .SymbolTag ;
4345import org .eclipse .lsp4j .TextDocumentIdentifier ;
44- import org .eclipse .lsp4j .legacy . typeHierarchy . ResolveTypeHierarchyItemParams ;
45- import org .eclipse .lsp4j .legacy . typeHierarchy . TypeHierarchyDirection ;
46- import org .eclipse .lsp4j .legacy . typeHierarchy . TypeHierarchyItem ;
47- import org .eclipse .lsp4j .legacy . typeHierarchy . TypeHierarchyParams ;
46+ import org .eclipse .lsp4j .TypeHierarchyItem ;
47+ import org .eclipse .lsp4j .TypeHierarchyPrepareParams ;
48+ import org .eclipse .lsp4j .TypeHierarchySubtypesParams ;
49+ import org .eclipse .lsp4j .TypeHierarchySupertypesParams ;
4850
49- public class TypeHierarchyCommand {
51+ public class TypeHierarchyHandler {
5052
51- public TypeHierarchyItem typeHierarchy (TypeHierarchyParams params , IProgressMonitor monitor ) {
53+ public enum TypeHierarchyDirection {
54+ Subtype , Supertype ;
55+ }
56+
57+ private static class TypeHierarchyItemData {
58+ private String handleIdentifier ;
59+ private String methodIdentifier ;
60+ private String methodName ;
61+
62+ public TypeHierarchyItemData (String handleIdentifier , String methodIdentifier , String methodName ) {
63+ this .handleIdentifier = handleIdentifier ;
64+ this .methodIdentifier = methodIdentifier ;
65+ this .methodName = methodName ;
66+ }
67+
68+ private static TypeHierarchyItemData getTypeHierarchyItemData (Object data ) {
69+ if (data == null ) {
70+ return null ;
71+ }
72+ Map <String , String > map = JSONUtility .toModel (data , Map .class );
73+ String handleIdentifier = map .get ("element" );
74+ String methodIdentifier = map .get ("method" );
75+ String methodName = map .get ("method_name" );
76+ return new TypeHierarchyItemData (handleIdentifier , methodIdentifier , methodName );
77+ }
78+ }
79+
80+ public List <TypeHierarchyItem > prepareTypeHierarchy (TypeHierarchyPrepareParams params , IProgressMonitor monitor ) {
5281 if (params == null ) {
53- return null ;
82+ return Collections . emptyList () ;
5483 }
5584 TextDocumentIdentifier textDocument = params .getTextDocument ();
5685 if (textDocument == null ) {
57- return null ;
86+ return Collections . emptyList () ;
5887 }
5988 Position position = params .getPosition ();
6089 String uri = textDocument .getUri ();
61- TypeHierarchyDirection direction = params .getDirection ();
62- int resolve = params .getResolve ();
63- return getTypeHierarchy (uri , position , direction , resolve , null , monitor );
90+ return getTypeHierarchyItems (uri , position , monitor );
6491 }
6592
66- public TypeHierarchyItem resolveTypeHierarchy ( ResolveTypeHierarchyItemParams params , IProgressMonitor monitor ) {
67- if (params == null ) {
68- return null ;
93+ private List < TypeHierarchyItem > getTypeHierarchyItems ( String uri , Position position , IProgressMonitor monitor ) {
94+ if (uri == null || position == null ) {
95+ return Collections . emptyList () ;
6996 }
70- TypeHierarchyItem item = params .getItem ();
71- if (item == null ) {
72- return null ;
97+ try {
98+ IMember member = getMember (uri , position , monitor );
99+ IMethod targetMethod = null ;
100+ if (member instanceof IMethod ) {
101+ targetMethod = (IMethod ) member ;
102+ }
103+ TypeHierarchyItem item = targetMethod == null ? TypeHierarchyHandler .toTypeHierarchyItem (member ) : TypeHierarchyHandler .toTypeHierarchyItem (member , false , targetMethod );
104+ if (item == null ) {
105+ return Collections .emptyList ();
106+ }
107+ return Arrays .asList (item );
108+ } catch (JavaModelException e ) {
109+ return Collections .emptyList ();
73110 }
74- Range range = item .getRange ();
75- if (range == null ) {
76- return null ;
111+ }
112+
113+ public List <TypeHierarchyItem > getSupertypeItems (TypeHierarchySupertypesParams params , IProgressMonitor monitor ) {
114+ return getTypeHierarchyItems (params .getItem (), TypeHierarchyDirection .Supertype , monitor );
115+ }
116+
117+ public List <TypeHierarchyItem > getSubtypeItems (TypeHierarchySubtypesParams params , IProgressMonitor monitor ) {
118+ return getTypeHierarchyItems (params .getItem (), TypeHierarchyDirection .Subtype , monitor );
119+ }
120+
121+ private List <TypeHierarchyItem > getTypeHierarchyItems (TypeHierarchyItem item , TypeHierarchyDirection direction , IProgressMonitor monitor ) {
122+ TypeHierarchyItemData data = TypeHierarchyItemData .getTypeHierarchyItemData (item .getData ());
123+ if (data == null ) {
124+ return Collections .emptyList ();
77125 }
78- Position position = range .getStart ();
79- String uri = item .getUri ();
80- TypeHierarchyDirection direction = params .getDirection ();
81- int resolve = params .getResolve ();
82- return getTypeHierarchy (uri , position , direction , resolve , item , monitor );
126+ IJavaElement element = JavaCore .create (data .handleIdentifier );
127+ IMember member = null ;
128+ IMethod targetMethod = null ;
129+ if (data .methodIdentifier != null ) {
130+ targetMethod = (IMethod ) JavaCore .create (data .methodIdentifier );
131+ }
132+ if (element instanceof IType || element instanceof IMethod ) {
133+ member = (IMember ) element ;
134+ } else if (element instanceof IOrdinaryClassFile classFile ) {
135+ member = classFile .getType ();
136+ } else {
137+ return Collections .emptyList ();
138+ }
139+ return resolveTypeHierarchyItems (member , targetMethod , direction , monitor );
83140 }
84141
85- private TypeHierarchyItem getTypeHierarchy (String uri , Position position , TypeHierarchyDirection direction , int resolve , TypeHierarchyItem itemInput , IProgressMonitor monitor ) {
86- if (uri == null || position == null || direction == null ) {
87- return null ;
142+ private List <TypeHierarchyItem > resolveTypeHierarchyItems (IMember member , IMethod targetMethod , TypeHierarchyDirection direction , IProgressMonitor monitor ) {
143+ if (monitor .isCanceled ()) {
144+ return Collections .emptyList ();
145+ }
146+ IType type = null ;
147+ if (member instanceof IType ) {
148+ type = (IType ) member ;
149+ } else {
150+ type = member .getDeclaringType ();
88151 }
89152 try {
90- IMember member = null ;
91- IMethod targetMethod = null ;
92- if (itemInput == null ) {
93- member = getMember (uri , position , monitor );
94- if (member instanceof IMethod ) {
95- targetMethod = (IMethod ) member ;
96- }
153+ ITypeHierarchy typeHierarchy = null ;
154+ List <TypeHierarchyItem > items = new ArrayList <>();
155+ IType [] hierarchyTypes = null ;
156+ if (direction == TypeHierarchyDirection .Supertype ) {
157+ typeHierarchy = type .newSupertypeHierarchy (DefaultWorkingCopyOwner .PRIMARY , monitor );
158+ hierarchyTypes = typeHierarchy .getSupertypes (type );
97159 } else {
98- Map <String , String > data = JSONUtility .toModel (itemInput .getData (), Map .class );
99- String handleIdentifier = data .get ("element" );
100- IJavaElement element = JavaCore .create (handleIdentifier );
101- String methodIdentifier = data .get ("method" );
102- if (methodIdentifier != null ) {
103- targetMethod = (IMethod ) JavaCore .create (methodIdentifier );
104- }
105- if (element instanceof IType || element instanceof IMethod ) {
106- member = (IMember ) element ;
107- } else if (element instanceof IOrdinaryClassFile classFile ) {
108- member = classFile .getType ();
160+ ICompilationUnit [] workingCopies = JavaModelManager .getJavaModelManager ().getWorkingCopies (DefaultWorkingCopyOwner .PRIMARY , true );
161+ typeHierarchy = type .newTypeHierarchy (workingCopies , monitor );
162+ hierarchyTypes = typeHierarchy .getSubtypes (type );
163+ }
164+ for (IType hierarchyType : hierarchyTypes ) {
165+ TypeHierarchyItem item = null ;
166+ if (targetMethod != null ) {
167+ IMethod [] matches = hierarchyType .findMethods (targetMethod );
168+ boolean excludeMember = matches == null || matches .length == 0 ;
169+ // Do not show java.lang.Object unless target method is based there
170+ if (!excludeMember || !"java.lang.Object" .equals (hierarchyType .getFullyQualifiedName ())) {
171+ item = TypeHierarchyHandler .toTypeHierarchyItem (excludeMember ? hierarchyType : matches [0 ], excludeMember , targetMethod );
172+ }
109173 } else {
110- return null ;
174+ item = TypeHierarchyHandler . toTypeHierarchyItem ( hierarchyType ) ;
111175 }
176+ if (item == null ) {
177+ continue ;
178+ }
179+ items .add (item );
112180 }
113- TypeHierarchyItem item = TypeHierarchyCommand .toTypeHierarchyItem (member );
114- if (item == null ) {
115- return null ;
116- }
117- resolve (item , member , targetMethod , direction , resolve , monitor );
118- return item ;
181+ return items ;
119182 } catch (JavaModelException e ) {
120- return null ;
183+ return Collections . emptyList () ;
121184 }
122185 }
123186
@@ -160,10 +223,10 @@ private static TypeHierarchyItem toTypeHierarchyItem(IMember member, boolean exc
160223 if (location == null || selectLocation == null ) {
161224 return null ;
162225 }
163- TypeHierarchyItem item = new TypeHierarchyItem ();
164- item . setRange ( location .getRange () );
165- item . setUri ( location .getUri () );
166- item . setSelectionRange ( selectLocation .getRange () );
226+
227+ Range range = location .getRange ();
228+ String uri = location .getUri ();
229+ Range selectionRange = selectLocation .getRange ();
167230
168231 IType type = null ;
169232 if (member instanceof IType ) {
@@ -172,20 +235,25 @@ private static TypeHierarchyItem toTypeHierarchyItem(IMember member, boolean exc
172235 type = member .getDeclaringType ();
173236 }
174237
238+ String name = null ;
239+ String detail = null ;
175240 String fullyQualifiedName = type .getFullyQualifiedName ();
176241 int index = fullyQualifiedName .lastIndexOf ('.' );
177242 if (index >= 1 && index < fullyQualifiedName .length () - 1 && !type .isAnonymous ()) {
178- item . setName ( fullyQualifiedName .substring (index + 1 ) );
179- item . setDetail ( fullyQualifiedName .substring (0 , index ) );
243+ name = fullyQualifiedName .substring (index + 1 );
244+ detail = fullyQualifiedName .substring (0 , index );
180245 } else {
181- item . setName ( JDTUtils .getName (type ) );
246+ name = JDTUtils .getName (type );
182247 IPackageFragment packageFragment = type .getPackageFragment ();
183248 if (packageFragment != null ) {
184- item . setDetail ( packageFragment .getElementName () );
249+ detail = packageFragment .getElementName ();
185250 }
186251 }
187- item .setKind (excludeMember ? SymbolKind .Null : DocumentSymbolHandler .mapKind (type ));
188- item .setDeprecated (JDTUtils .isDeprecated (member ));
252+ SymbolKind kind = excludeMember ? SymbolKind .Null : DocumentSymbolHandler .mapKind (type );
253+ List <SymbolTag > tags = new ArrayList <>();
254+ if (JDTUtils .isDeprecated (member )) {
255+ tags .add (SymbolTag .Deprecated );
256+ }
189257 Map <String , String > data = new HashMap <>();
190258 data .put ("element" , member .getHandleIdentifier ());
191259 if (targetMethod != null ) {
@@ -195,6 +263,8 @@ private static TypeHierarchyItem toTypeHierarchyItem(IMember member, boolean exc
195263 data .put ("method" , member .getHandleIdentifier ());
196264 data .put ("method_name" , member .getElementName ());
197265 }
266+ TypeHierarchyItem item = new TypeHierarchyItem (name , kind , uri , range , selectionRange , detail );
267+ item .setTags (tags );
198268 item .setData (data );
199269 return item ;
200270 }
@@ -206,68 +276,4 @@ private static Location getLocation(IMember member, LocationType locationType) t
206276 }
207277 return location ;
208278 }
209-
210- private void resolve (TypeHierarchyItem item , IMember member , IMethod targetMethod , TypeHierarchyDirection direction , int resolve , IProgressMonitor monitor ) throws JavaModelException {
211- if (monitor .isCanceled () || resolve <= 0 ) {
212- return ;
213- }
214-
215- IType type = null ;
216- if (member instanceof IType ) {
217- type = (IType ) member ;
218- } else {
219- type = member .getDeclaringType ();
220- }
221-
222- ITypeHierarchy typeHierarchy ;
223- if (direction == TypeHierarchyDirection .Parents ) {
224- typeHierarchy = type .newSupertypeHierarchy (DefaultWorkingCopyOwner .PRIMARY , monitor );
225- } else {
226- ICompilationUnit [] workingCopies = JavaModelManager .getJavaModelManager ().getWorkingCopies (DefaultWorkingCopyOwner .PRIMARY , true );
227- typeHierarchy = type .newTypeHierarchy (workingCopies , monitor );
228- }
229- if (direction == TypeHierarchyDirection .Children || direction == TypeHierarchyDirection .Both ) {
230- List <TypeHierarchyItem > childrenItems = new ArrayList <>();
231- IType [] children = typeHierarchy .getSubtypes (type );
232- for (IType childType : children ) {
233- TypeHierarchyItem childItem = null ;
234- if (targetMethod != null ) {
235- IMethod [] matches = childType .findMethods (targetMethod );
236- boolean excludeMember = matches == null || matches .length == 0 ;
237- childItem = TypeHierarchyCommand .toTypeHierarchyItem (excludeMember ? childType : matches [0 ], excludeMember , targetMethod );
238- } else {
239- childItem = TypeHierarchyCommand .toTypeHierarchyItem (childType );
240- }
241- if (childItem == null ) {
242- continue ;
243- }
244- resolve (childItem , childType , targetMethod , direction , resolve - 1 , monitor );
245- childrenItems .add (childItem );
246- }
247- item .setChildren (childrenItems );
248- }
249- if (direction == TypeHierarchyDirection .Parents || direction == TypeHierarchyDirection .Both ) {
250- List <TypeHierarchyItem > parentsItems = new ArrayList <>();
251- IType [] parents = typeHierarchy .getSupertypes (type );
252- for (IType parentType : parents ) {
253- TypeHierarchyItem parentItem = null ;
254- if (targetMethod != null ) {
255- IMethod [] matches = parentType .findMethods (targetMethod );
256- boolean excludeMember = matches == null || matches .length == 0 ;
257- // Do not show java.lang.Object unless target method is based there
258- if (!excludeMember || !"java.lang.Object" .equals (parentType .getFullyQualifiedName ())) {
259- parentItem = TypeHierarchyCommand .toTypeHierarchyItem (excludeMember ? parentType : matches [0 ], excludeMember , targetMethod );
260- }
261- } else {
262- parentItem = TypeHierarchyCommand .toTypeHierarchyItem (parentType );
263- }
264- if (parentItem == null ) {
265- continue ;
266- }
267- resolve (parentItem , parentType , targetMethod , direction , resolve - 1 , monitor );
268- parentsItems .add (parentItem );
269- }
270- item .setParents (parentsItems );
271- }
272- }
273279}
0 commit comments