diff --git a/java.source.base/apichanges.xml b/java.source.base/apichanges.xml --- a/java.source.base/apichanges.xml +++ b/java.source.base/apichanges.xml @@ -49,6 +49,20 @@ Java Source API + + + ClassIndex SearchKind extended by FUNCTIONAL_IMPLEMENTORS + + + + + + Added a possibility to ClassIndex to search a lambda + implementations. + + + + ClassIndex returns resources from binaryroots diff --git a/java.source.base/nbproject/project.properties b/java.source.base/nbproject/project.properties --- a/java.source.base/nbproject/project.properties +++ b/java.source.base/nbproject/project.properties @@ -47,7 +47,7 @@ javadoc.title=Java Source Base javadoc.arch=${basedir}/arch.xml javadoc.apichanges=${basedir}/apichanges.xml -spec.version.base=2.8.0 +spec.version.base=2.9.0 test.qa-functional.cp.extra=${refactoring.java.dir}/modules/ext/nb-javac-api.jar test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:\ ${o.n.core.dir}/lib/boot.jar:\ diff --git a/java.source.base/src/org/netbeans/api/java/source/ClassIndex.java b/java.source.base/src/org/netbeans/api/java/source/ClassIndex.java --- a/java.source.base/src/org/netbeans/api/java/source/ClassIndex.java +++ b/java.source.base/src/org/netbeans/api/java/source/ClassIndex.java @@ -198,6 +198,8 @@ /** * The returned class has to extend or implement given element + *//** + * The returned class has to extend or implement given element */ IMPLEMENTORS, @@ -214,7 +216,13 @@ /** * The returned class contains references to the element type */ - TYPE_REFERENCES, + TYPE_REFERENCES, + + /** + * The returned class contains a lambda implementation of given functional interface. + * @since 2.9 + */ + FUNCTIONAL_IMPLEMENTORS; }; /** @@ -831,8 +839,8 @@ final Set result = EnumSet.noneOf(ClassIndexImpl.UsageType.class); for (ClassIndex.SearchKind sk : kind) { switch (sk) { - case METHOD_REFERENCES: - result.add(ClassIndexImpl.UsageType.METHOD_REFERENCE); + case METHOD_REFERENCES: + result.add(ClassIndexImpl.UsageType.METHOD_REFERENCE); break; case FIELD_REFERENCES: result.add(ClassIndexImpl.UsageType.FIELD_REFERENCE); @@ -860,6 +868,9 @@ throw new IllegalArgumentException (); } break; + case FUNCTIONAL_IMPLEMENTORS: + result.add(ClassIndexImpl.UsageType.FUNCTIONAL_IMPLEMENTORS); + break; default: throw new IllegalArgumentException (); } diff --git a/java.source.base/src/org/netbeans/modules/java/source/indexing/JavaIndex.java b/java.source.base/src/org/netbeans/modules/java/source/indexing/JavaIndex.java --- a/java.source.base/src/org/netbeans/modules/java/source/indexing/JavaIndex.java +++ b/java.source.base/src/org/netbeans/modules/java/source/indexing/JavaIndex.java @@ -81,7 +81,7 @@ public final class JavaIndex { public static final String NAME = "java"; //NOI18N - public static final int VERSION = 14; + public static final int VERSION = 15; static final Logger LOG = Logger.getLogger(JavaIndex.class.getName()); private static final String CLASSES = "classes"; //NOI18N private static final String APT_SOURCES = "sources"; //NOI18N diff --git a/java.source.base/src/org/netbeans/modules/java/source/usages/ClassIndexImpl.java b/java.source.base/src/org/netbeans/modules/java/source/usages/ClassIndexImpl.java --- a/java.source.base/src/org/netbeans/modules/java/source/usages/ClassIndexImpl.java +++ b/java.source.base/src/org/netbeans/modules/java/source/usages/ClassIndexImpl.java @@ -87,7 +87,8 @@ SUPER_INTERFACE, FIELD_REFERENCE, METHOD_REFERENCE, - TYPE_REFERENCE; + TYPE_REFERENCE, + FUNCTIONAL_IMPLEMENTORS; } /** diff --git a/java.source.base/src/org/netbeans/modules/java/source/usages/SourceAnalyzerFactory.java b/java.source.base/src/org/netbeans/modules/java/source/usages/SourceAnalyzerFactory.java --- a/java.source.base/src/org/netbeans/modules/java/source/usages/SourceAnalyzerFactory.java +++ b/java.source.base/src/org/netbeans/modules/java/source/usages/SourceAnalyzerFactory.java @@ -778,6 +778,25 @@ } @Override + public Void visitLambdaExpression( + @NonNull final LambdaExpressionTree node, + @NonNull final Map, UsagesData> p) { + final Type type = ((JCTree.JCLambda)node).type; + if (type != null) { + final Symbol sym = type.tsym; + if (sym != null) { + if (sym != null && sym.getKind().isInterface()) { + addUsage(sym, + activeClass.peek(), + p, + ClassIndexImpl.UsageType.FUNCTIONAL_IMPLEMENTORS); + } + } + } + return super.visitLambdaExpression(node, p); + } + + @Override @CheckForNull public Void visitVariable(@NonNull final VariableTree node, @NonNull final Map, UsagesData> p) { Symbol s = ((JCTree.JCVariableDecl)node).sym; diff --git a/refactoring.java/nbproject/project.xml b/refactoring.java/nbproject/project.xml --- a/refactoring.java/nbproject/project.xml +++ b/refactoring.java/nbproject/project.xml @@ -177,7 +177,7 @@ - 2.6 + 2.9 diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaWhereUsedQueryPlugin.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaWhereUsedQueryPlugin.java --- a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaWhereUsedQueryPlugin.java +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaWhereUsedQueryPlugin.java @@ -56,6 +56,7 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; +import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.fileinfo.NonRecursiveFolder; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.platform.JavaPlatform; @@ -296,17 +297,27 @@ } } else if (el.getKind().isClass() || el.getKind().isInterface()) { if (isFindSubclasses || isFindDirectSubclassesOnly) { - EnumSet searchKind = EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS); if (isFindDirectSubclassesOnly) { + EnumSet searchKind = EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS); + if (el.getKind() == ElementKind.INTERFACE) { + searchKind.add(ClassIndex.SearchKind.FUNCTIONAL_IMPLEMENTORS); + } //get direct implementors from index sourceSet.addAll(idx.getResources(ElementHandle.create((TypeElement) el), searchKind, searchScopeType, resourceType)); } else { - Set implementorsAsHandles = RefactoringUtils.getImplementorsAsHandles(idx, cpInfo, (TypeElement)el, cancel); + Set> implementorsAsHandles = RefactoringUtils.getImplementorsAsHandles(idx, cpInfo, (TypeElement)el, cancel); if (cancel != null && cancel.get()) { sourceSet.clear(); return; } - sourceSet.addAll(SourceUtilsEx.getFiles((Collection>) implementorsAsHandles, cpInfo, cancel)); + sourceSet.addAll(SourceUtilsEx.getFiles((Collection>)(Collection)implementorsAsHandles, cpInfo, cancel)); + if (el.getKind() == ElementKind.INTERFACE) { + sourceSet.addAll(getFunctionalSubtypes( + ElementHandle.create((TypeElement)el), + implementorsAsHandles, + cpInfo, + searchScopeType)); + } } } else { //get type references from index @@ -550,6 +561,25 @@ } } + @NonNull + private static Collection getFunctionalSubtypes( + @NonNull final ElementHandle base, + @NonNull final Collection> subtypes, + @NonNull final ClasspathInfo cpInfo, + @NonNull final Set scope) { + assert base.getKind() == ElementKind.INTERFACE; + final ClassIndex index = cpInfo.getClassIndex(); + final Set fncKind = EnumSet.of(ClassIndex.SearchKind.FUNCTIONAL_IMPLEMENTORS); + final Set result = new HashSet<>(); + result.addAll(index.getResources(base, fncKind, scope)); + for (ElementHandle e : subtypes) { + if (e.getKind() == ElementKind.INTERFACE) { + result.addAll(index.getResources(e, fncKind, scope)); + } + } + return result; + } + private class FindTask implements CancellableTask { private final RefactoringElementsBag elements;