This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 262281
Collapse All | Expand All

(-)a/java.source.base/apichanges.xml (+15 lines)
Lines 49-54 Link Here
49
    <apidef name="javasource_base">Java Source API</apidef>
49
    <apidef name="javasource_base">Java Source API</apidef>
50
</apidefs>
50
</apidefs>
51
<changes>
51
<changes>
52
    <change id="utilities.findVisibleElements">
53
        <api name="javasource_base"/>
54
        <summary>List elements with their definining Scope</summary>
55
        <version major="1" minor="2.16"/>
56
        <date day="31" month="5" year="2016"/>
57
        <author login="sdedic"/>
58
        <compatibility addition="yes" binary="compatible" source="compatible"/>
59
        <description>
60
            Allows to enumerate Elements matching passed <code>ElementFilter</code> according
61
            to hiding and inheritance rules. The method may be useful to list elements matching certain
62
            criteria, or to check whether an element exists and find what class/method defined it.
63
        </description>
64
        <class name="ElementUtilities" package="org.netbeans.api.java.source"/>
65
        <issue number="262281"/>
66
    </change>
52
    <change id="utilities.implementAndOverride.defaultMethods">
67
    <change id="utilities.implementAndOverride.defaultMethods">
53
        <api name="javasource_base"/>
68
        <api name="javasource_base"/>
54
        <summary>Allow to return also unimplemented default methods</summary>
69
        <summary>Allow to return also unimplemented default methods</summary>
(-)a/java.source.base/nbproject/project.properties (-1 / +1 lines)
Lines 47-53 Link Here
47
javadoc.title=Java Source Base
47
javadoc.title=Java Source Base
48
javadoc.arch=${basedir}/arch.xml
48
javadoc.arch=${basedir}/arch.xml
49
javadoc.apichanges=${basedir}/apichanges.xml
49
javadoc.apichanges=${basedir}/apichanges.xml
50
spec.version.base=2.15.0
50
spec.version.base=2.16.0
51
test.qa-functional.cp.extra=${refactoring.java.dir}/modules/ext/nb-javac-api.jar
51
test.qa-functional.cp.extra=${refactoring.java.dir}/modules/ext/nb-javac-api.jar
52
test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:\
52
test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:\
53
    ${o.n.core.dir}/lib/boot.jar:\
53
    ${o.n.core.dir}/lib/boot.jar:\
(-)a/java.source.base/src/org/netbeans/api/java/source/ElementUtilities.java (+114 lines)
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) {

Return to bug 262281