Lines 71-80
Link Here
|
71 |
import com.sun.tools.javac.util.Context; |
71 |
import com.sun.tools.javac.util.Context; |
72 |
import com.sun.tools.javac.util.Names; |
72 |
import com.sun.tools.javac.util.Names; |
73 |
import com.sun.tools.javadoc.DocEnv; |
73 |
import com.sun.tools.javadoc.DocEnv; |
|
|
74 |
import java.util.ArrayDeque; |
74 |
|
75 |
|
75 |
import java.util.ArrayList; |
76 |
import java.util.ArrayList; |
76 |
import java.util.Collection; |
77 |
import java.util.Collection; |
77 |
import java.util.Collections; |
78 |
import java.util.Collections; |
|
|
79 |
import java.util.Deque; |
78 |
import java.util.EnumSet; |
80 |
import java.util.EnumSet; |
79 |
import java.util.HashMap; |
81 |
import java.util.HashMap; |
80 |
import java.util.HashSet; |
82 |
import java.util.HashSet; |
Lines 84-89
Link Here
|
84 |
import java.util.ListIterator; |
86 |
import java.util.ListIterator; |
85 |
import java.util.Map; |
87 |
import java.util.Map; |
86 |
import java.util.Set; |
88 |
import java.util.Set; |
|
|
89 |
import java.util.Stack; |
87 |
|
90 |
|
88 |
import javax.lang.model.element.Element; |
91 |
import javax.lang.model.element.Element; |
89 |
import javax.lang.model.element.ElementKind; |
92 |
import javax.lang.model.element.ElementKind; |
Lines 109-114
Link Here
|
109 |
import org.netbeans.api.annotations.common.NullAllowed; |
112 |
import org.netbeans.api.annotations.common.NullAllowed; |
110 |
import org.netbeans.modules.java.source.builder.ElementsService; |
113 |
import org.netbeans.modules.java.source.builder.ElementsService; |
111 |
import org.netbeans.modules.java.source.JavadocEnv; |
114 |
import org.netbeans.modules.java.source.JavadocEnv; |
|
|
115 |
import org.openide.util.Parameters; |
112 |
|
116 |
|
113 |
/** |
117 |
/** |
114 |
* |
118 |
* |
Lines 320-325
Link Here
|
320 |
return members; |
324 |
return members; |
321 |
} |
325 |
} |
322 |
|
326 |
|
|
|
327 |
/** |
328 |
* Finds symbols which satisfy the acceptor visible in the passed scope. The method returns a Map keyed by the |
329 |
* found Elements. Each Element is mapped to the closest Scope which introduced the Element. For example, a field declared |
330 |
* by an outer class will map to that outer class' scope. An accessible field inherited from outer class' superclass |
331 |
* will <b>also</b> map to the outer class' scope. The caller can then determine, based on {@link Element#getEnclosingElement()} and |
332 |
* the mapped Scope whether the symbol is directly declared, or inherited. Non-member symbols (variables, parameters, try resources, ...) |
333 |
* map to Scope of their defining Method. |
334 |
* <p/> |
335 |
* If an Element from outer Scope is hidden by a similar Element |
336 |
* in inner scope, only the Element visible to the passed Scope is returned. For example, if both the starting (inner) class and its outer class |
337 |
* define method m(), only InnerClass.m() will be returned. |
338 |
* <p/> |
339 |
* Note that {@link Scope#getEnclosingMethod()} returns non-null even for class scopes of local or anonymous classes; check both {@link Scope#getEnclosingClass()} |
340 |
* and {@link Scope#getEnclosingMethod()} and their relationship to get the appropriate Element associated with the Scope. |
341 |
* |
342 |
* @param scope the initial search scope |
343 |
* @param acceptor the element filter. |
344 |
* @return Mapping of visible and accessible Elements to their defining {@link Scope}s (which introduced them). |
345 |
* @see Scope |
346 |
* @since 2.16 |
347 |
*/ |
348 |
public @NonNull Map<? extends Element, Scope> findElementsAndOrigins(@NonNull Scope scope, ElementAcceptor acceptor) { |
349 |
Parameters.notNull("scope", scope); // NOI18N |
350 |
final Map<Element, Scope> result = new HashMap<>(); |
351 |
|
352 |
if (acceptor == null) { |
353 |
acceptor = ALL_ACCEPTOR; |
354 |
} |
355 |
Map<String, List<Element>> members = null; |
356 |
Elements elements = JavacElements.instance(ctx); |
357 |
Types types = JavacTypes.instance(ctx); |
358 |
TypeElement cls; |
359 |
Deque<Scope> outerScopes = new ArrayDeque(); |
360 |
Deque<Map> visibleEls = new ArrayDeque(); |
361 |
Element current = null; |
362 |
|
363 |
while (scope != null) { |
364 |
cls = scope.getEnclosingClass(); |
365 |
if (cls != null) { |
366 |
Element e; |
367 |
ExecutableElement ee = scope.getEnclosingMethod(); |
368 |
if (ee != null && ee.getEnclosingElement() != cls) { |
369 |
e = ee; |
370 |
} else { |
371 |
e = cls; |
372 |
} |
373 |
if (e != current) { |
374 |
// push at the scope entry |
375 |
members = new HashMap<>(); |
376 |
outerScopes.push(scope); |
377 |
visibleEls.push(members); |
378 |
} |
379 |
for (Element local : scope.getLocalElements()) { |
380 |
if (acceptor == null || acceptor.accept(local, null)) { |
381 |
addIfNotHidden(local, members, local.getSimpleName().toString(), elements, types); |
382 |
} |
383 |
} |
384 |
TypeMirror type = cls.asType(); |
385 |
for (Element member : elements.getAllMembers(cls)) { |
386 |
if (acceptor == null || acceptor.accept(member, type)) { |
387 |
addIfNotHidden(member, members, member.getSimpleName().toString(), elements, types); |
388 |
} |
389 |
} |
390 |
} else { |
391 |
for (Element local : scope.getLocalElements()) { |
392 |
if (!local.getKind().isClass() && !local.getKind().isInterface() && |
393 |
(acceptor == null || local.getEnclosingElement() != null && acceptor.accept(local, local.getEnclosingElement().asType()))) { |
394 |
addIfNotHidden(local, members, local.getSimpleName().toString(), elements, types); |
395 |
} |
396 |
} |
397 |
} |
398 |
scope = scope.getEnclosingScope(); |
399 |
} |
400 |
|
401 |
while (!outerScopes.isEmpty()) { |
402 |
Scope x = outerScopes.pop(); |
403 |
Collection<List<Element>> vals = (Collection<List<Element>>)visibleEls.pop().values(); |
404 |
for (List<Element> col : vals) { |
405 |
for (Element e : col) { |
406 |
result.put(e, x); |
407 |
} |
408 |
} |
409 |
} |
410 |
|
411 |
return result; |
412 |
} |
413 |
|
414 |
private static final ElementAcceptor ALL_ACCEPTOR = new ElementAcceptor() { |
415 |
@Override |
416 |
public boolean accept(Element e, TypeMirror type) { |
417 |
return true; |
418 |
} |
419 |
}; |
420 |
|
421 |
private void addIfNotHidden(Element local, Map<String, List<Element>> members, String name, Elements elements, Types types) { |
422 |
List<Element> namedMembers = members.get(name); |
423 |
if (namedMembers != null) { |
424 |
// PENDING: isHidden will not report variables, which are effectively hidden by anonymous or local class' variables. |
425 |
// there is no way how to denote such hidden local variable/paremeter from the inner class, so such vars should |
426 |
// not be reported. |
427 |
if (isHidden(local, namedMembers, elements, types)) { |
428 |
return; |
429 |
} |
430 |
} else { |
431 |
namedMembers = new ArrayList<>(); |
432 |
members.put(name, namedMembers); |
433 |
} |
434 |
namedMembers.add(local); |
435 |
} |
436 |
|
323 |
/**Return members declared in the given scope. |
437 |
/**Return members declared in the given scope. |
324 |
*/ |
438 |
*/ |
325 |
public Iterable<? extends Element> getLocalMembersAndVars(Scope scope, ElementAcceptor acceptor) { |
439 |
public Iterable<? extends Element> getLocalMembersAndVars(Scope scope, ElementAcceptor acceptor) { |