javac ast indices is applied for lambda search
authorDmitry Batkovich <dmitry.batkovich@jetbrains.com>
Wed, 28 Sep 2016 15:27:36 +0000 (18:27 +0300)
committerDmitry Batkovich <dmitry.batkovich@jetbrains.com>
Wed, 28 Sep 2016 15:27:36 +0000 (18:27 +0300)
17 files changed:
java/compiler/impl/src/com/intellij/compiler/CompilerReferenceReader.java
java/compiler/impl/src/com/intellij/compiler/CompilerReferenceServiceImpl.java
java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerElementAsLightUsageConverter.java [new file with mode: 0644]
java/java-indexing-impl/src/com/intellij/compiler/CompilerElement.java [new file with mode: 0644]
java/java-indexing-impl/src/com/intellij/compiler/CompilerReferenceService.java
java/java-indexing-impl/src/com/intellij/compiler/CompilerSearchAdapter.java [moved from java/compiler/impl/src/com/intellij/compiler/CompilerReferenceConverter.java with 73% similarity]
java/java-indexing-impl/src/com/intellij/compiler/JavaBaseCompilerSearchAdapter.java [moved from java/compiler/impl/src/com/intellij/compiler/JavaCompilerReferenceConverter.java with 91% similarity]
java/java-indexing-impl/src/com/intellij/compiler/JavaCompilerReferencesInCodeScopeOptimizer.java
java/java-indexing-impl/src/com/intellij/compiler/JavaFunctionalExpressionCompilerSearchAdapter.java [new file with mode: 0644]
java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaFunctionalExpressionSearcher.java
java/java-tests/testData/compiler/bytecodeReferences/testLambda/Bar.java [new file with mode: 0644]
java/java-tests/testData/compiler/bytecodeReferences/testLambda/BarRef.java [new file with mode: 0644]
java/java-tests/testData/compiler/bytecodeReferences/testLambda/Foo.java [new file with mode: 0644]
java/java-tests/testData/compiler/bytecodeReferences/testLambda/FooImpl.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/compiler/CompilerReferencesTest.java
jps/jps-builders/src/org/jetbrains/jps/backwardRefs/CompilerElement.java [deleted file]
jps/jps-builders/src/org/jetbrains/jps/backwardRefs/LightUsage.java

index f2cd21248f22b86d1262e9721a9b1f72794d4f9d..681c7a400fffe910c2bdd1b15f4e3fa28ffb8854 100644 (file)
@@ -15,7 +15,9 @@
  */
 package com.intellij.compiler;
 
+import com.intellij.compiler.backwardRefs.CompilerElementAsLightUsageConverter;
 import com.intellij.compiler.server.BuildManager;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -24,7 +26,6 @@ import com.intellij.util.containers.Queue;
 import gnu.trove.TIntHashSet;
 import gnu.trove.TIntProcedure;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jps.backwardRefs.CompilerElement;
 import org.jetbrains.jps.backwardRefs.CompilerBackwardReferenceIndex;
 import org.jetbrains.jps.backwardRefs.LightUsage;
 
@@ -33,6 +34,8 @@ import java.io.IOException;
 import java.util.Collection;
 
 public class CompilerReferenceReader {
+  private final static Logger LOG = Logger.getInstance(CompilerReferenceReader.class);
+
   private final CompilerBackwardReferenceIndex myIndex;
 
   private CompilerReferenceReader(File buildDir) throws IOException {
@@ -40,25 +43,40 @@ public class CompilerReferenceReader {
   }
 
   @NotNull
-  public TIntHashSet findReferentFileIds(@NotNull CompilerElement element) {
-    LightUsage usage = element.asUsage(myIndex.getByteSeqEum());
+  public TIntHashSet findReferentFileIds(@NotNull CompilerElement element, @NotNull CompilerSearchAdapter adapter) {
+    LightUsage usage = null;
+    for (CompilerElementAsLightUsageConverter converter : CompilerElementAsLightUsageConverter.INSTANCES) {
+      usage = converter.asLightUsage(element, myIndex.getByteSeqEum());
+      if (usage != null) {
+        break;
+      }
+    }
+    LOG.assertTrue(usage != null);
 
     TIntHashSet set = new TIntHashSet();
-    for (int classId : getWholeHierarchy(usage.getOwner())) {
-      final LightUsage overriderUsage = usage.override(classId);
-      final Collection<Integer> usageFiles = myIndex.getBackwardReferenceMap().get(overriderUsage);
-      if (usageFiles != null) {
-        for (int fileId : usageFiles) {
-          final VirtualFile file = findFile(fileId);
-          if (file != null) {
-            set.add(((VirtualFileWithId)file).getId());
-          }
-        }
+    if (adapter.needOverrideElement()) {
+      for (int classId : getWholeHierarchy(usage.getOwner())) {
+        final LightUsage overriderUsage = usage.override(classId);
+        addUsages(overriderUsage, set);
       }
+    } else {
+      addUsages(usage, set);
     }
     return set;
   }
 
+  public void addUsages(LightUsage usage, TIntHashSet sink) {
+    final Collection<Integer> usageFiles = myIndex.getBackwardReferenceMap().get(usage);
+    if (usageFiles != null) {
+      for (int fileId : usageFiles) {
+        final VirtualFile file = findFile(fileId);
+        if (file != null) {
+          sink.add(((VirtualFileWithId)file).getId());
+        }
+      }
+    }
+  }
+
   public void close() {
     myIndex.close();
   }
index 6b5d54d773e7c256d146e61a58b578ef40f100d3..528ba969e261abdc09094d44418622e35c326543 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.intellij.compiler;
 
+import com.intellij.ide.highlighter.JavaFileType;
 import com.intellij.openapi.compiler.CompileContext;
 import com.intellij.openapi.compiler.CompileTask;
 import com.intellij.openapi.compiler.CompilerManager;
@@ -25,13 +26,12 @@ import com.intellij.openapi.roots.ModuleRootManager;
 import com.intellij.openapi.roots.ProjectFileIndex;
 import com.intellij.openapi.roots.ProjectRootManager;
 import com.intellij.openapi.roots.impl.LibraryScopeCache;
+import com.intellij.openapi.util.Key;
 import com.intellij.openapi.vfs.*;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.CachedValueProvider;
-import com.intellij.psi.util.CachedValuesManager;
-import com.intellij.psi.util.PsiModificationTracker;
+import com.intellij.psi.util.*;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.indexing.FileBasedIndex;
 import gnu.trove.THashSet;
@@ -39,17 +39,12 @@ import gnu.trove.TIntHashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
-import org.jetbrains.jps.backwardRefs.CompilerElement;
 
 import java.util.Collections;
 import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 public class CompilerReferenceServiceImpl extends CompilerReferenceService {
-  private static final CompilerReferenceConverter[] BYTECODE_CONVERTERS =
-    new CompilerReferenceConverter[]{new JavaCompilerReferenceConverter()};
-
+  private static final Key<ParameterizedCachedValue<GlobalSearchScope, CompilerSearchAdapter>> CACHE_KEY = Key.create("compiler.ref.service.search");
   private final ProjectFileIndex myProjectFileIndex;
   private final Set<Module> myChangedModules = ContainerUtil.newConcurrentSet();
   private final Set<FileType> myFileTypes;
@@ -62,8 +57,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService {
   public CompilerReferenceServiceImpl(Project project) {
     super(project);
     myProjectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
-    myFileTypes = Collections.unmodifiableSet(
-      Stream.of(BYTECODE_CONVERTERS).map(CompilerReferenceConverter::getAvailabilitySrcFileType).collect(Collectors.toSet()));
+    myFileTypes = Collections.unmodifiableSet(ContainerUtil.set(JavaFileType.INSTANCE));
   }
 
   @Override
@@ -143,21 +137,35 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService {
     closeReaderIfNeed();
   }
 
+
   @Nullable
   @Override
-  public GlobalSearchScope getMayContainReferencesInCodeScope(@NotNull PsiElement element) {
+  public GlobalSearchScope getMayContainReferencesInCodeScope(@NotNull PsiElement element, @NotNull CompilerSearchAdapter adapter) {
     if (!isServiceEnabled()) return null;
-    return CachedValuesManager.getCachedValue(element, () -> CachedValueProvider.Result.create(calculateMayContainReferencesScope(element), PsiModificationTracker.MODIFICATION_COUNT));
-  }
 
+    final ParameterizedCachedValueProvider<GlobalSearchScope, CompilerSearchAdapter> cachedValueProvider =
+      new ParameterizedCachedValueProvider<GlobalSearchScope, CompilerSearchAdapter>() {
+        @Nullable
+        @Override
+        public CachedValueProvider.Result<GlobalSearchScope> compute(CompilerSearchAdapter param) {
+          return CachedValueProvider.Result
+            .create(calculateMayContainReferencesScope(element, param), PsiModificationTracker.MODIFICATION_COUNT);
+        }
+      };
+    return CachedValuesManager.getManager(myProject).getParameterizedCachedValue(element,
+                                                                                 CACHE_KEY,
+                                                                                 cachedValueProvider,
+                                                                                 false,
+                                                                                 adapter);
+  }
 
   private boolean isServiceEnabled() {
     return myReader != null && isEnabled();
   }
 
   @Nullable
-  private GlobalSearchScope calculateMayContainReferencesScope(@NotNull PsiElement element) {
-    TIntHashSet referentFileIds = getReferentFileIds(element);
+  private GlobalSearchScope calculateMayContainReferencesScope(@NotNull PsiElement element, CompilerSearchAdapter adapter) {
+    TIntHashSet referentFileIds = getReferentFileIds(element, adapter);
     if (referentFileIds == null) return null;
 
     return new ScopeWithBytecodeReferences(referentFileIds)
@@ -167,7 +175,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService {
   }
 
   @Nullable
-  private TIntHashSet getReferentFileIds(@NotNull PsiElement element) {
+  private TIntHashSet getReferentFileIds(@NotNull PsiElement element, @NotNull CompilerSearchAdapter adapter) {
     final PsiFile file = element.getContainingFile();
     if (file == null) return null;
     final VirtualFile vFile = file.getVirtualFile();
@@ -181,32 +189,16 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService {
     if (myMayContainInvalidDataScope.contains(vFile)) {
       return null;
     }
-    final FileType type = vFile.getFileType();
-    CompilerElement[] compilerElements = null;
-    if (place == ElementPlace.SRC) {
-      for (CompilerReferenceConverter converter : BYTECODE_CONVERTERS) {
-        if (converter.getAvailabilitySrcFileType().equals(type)) {
-          final CompilerElement compilerElement = converter.sourceElementAsCompilerElement(element);
-          compilerElements = compilerElement == null ? CompilerElement.EMPTY_ARRAY : new CompilerElement[]{compilerElement};
-          break;
-        }
-      }
-    }
-    else {
-      for (CompilerReferenceConverter converter : BYTECODE_CONVERTERS) {
-        compilerElements = converter.libraryElementAsCompilerElements(element);
-        if (compilerElements.length != 0) {
-          break;
-        }
-      }
-    }
-    if (compilerElements == null || compilerElements.length == 0) return null;
+    CompilerElement[] compilerElements = place == ElementPlace.SRC
+                                         ? new CompilerElement[]{adapter.asCompilerElement(element)}
+                                         : adapter.libraryElementAsCompilerElements(element);
+    if (compilerElements.length == 0) return null;
 
     synchronized (myLock) {
       if (myReader == null) return null;
       TIntHashSet referentFileIds = new TIntHashSet();
       for (CompilerElement compilerElement : compilerElements) {
-        referentFileIds.addAll(myReader.findReferentFileIds(compilerElement).toArray());
+        referentFileIds.addAll(myReader.findReferentFileIds(compilerElement, adapter).toArray());
       }
       return referentFileIds;
     }
@@ -231,9 +223,9 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService {
 
   @TestOnly
   @Nullable
-  public Set<VirtualFile> getReferentFiles(@NotNull PsiElement element) {
+  public Set<VirtualFile> getReferentFiles(@NotNull PsiElement element, @NotNull CompilerSearchAdapter adapter) {
     FileBasedIndex fileIndex = FileBasedIndex.getInstance();
-    final TIntHashSet ids = getReferentFileIds(element);
+    final TIntHashSet ids = getReferentFileIds(element, adapter);
     if (ids == null) return null;
     Set<VirtualFile> fileSet = new THashSet<>();
     ids.forEach(id -> {
diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerElementAsLightUsageConverter.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerElementAsLightUsageConverter.java
new file mode 100644 (file)
index 0000000..3e76c2a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.compiler.backwardRefs;
+
+import com.intellij.compiler.CompilerElement;
+import com.sun.tools.javac.util.Convert;
+import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator;
+import org.jetbrains.jps.backwardRefs.LightUsage;
+
+public interface CompilerElementAsLightUsageConverter {
+  CompilerElementAsLightUsageConverter[] INSTANCES = new CompilerElementAsLightUsageConverter[]{new Java()};
+
+  LightUsage asLightUsage(CompilerElement element, ByteArrayEnumerator names);
+
+  class Java implements CompilerElementAsLightUsageConverter {
+    @Override
+    public LightUsage asLightUsage(CompilerElement element, ByteArrayEnumerator names) {
+      if (element instanceof CompilerElement.CompilerClass) {
+        return new LightUsage.LightClassUsage(id(((CompilerElement.CompilerClass)element).getJavacName(), names));
+
+      }
+      else if (element instanceof CompilerElement.CompilerMethod) {
+        final CompilerElement.CompilerMethod method = (CompilerElement.CompilerMethod)element;
+        return new LightUsage.LightMethodUsage(id(method.getJavacClassName(), names),
+                                               id(method.getJavacMethodName(), names),
+                                               method.getJavacParameterCount());
+
+      }
+      else if (element instanceof CompilerElement.CompilerField) {
+        final CompilerElement.CompilerField field = (CompilerElement.CompilerField)element;
+        return new LightUsage.LightFieldUsage(id(field.getJavacClassName(), names),
+                                              id(field.getJavacName(), names));
+
+      }
+      else if (element instanceof CompilerElement.CompilerFunExpr) {
+        final CompilerElement.CompilerFunExpr field = (CompilerElement.CompilerFunExpr)element;
+        return new LightUsage.LightFunExprUsage(id(field.getJavacClassName(), names));
+
+      }
+      return null;
+    }
+
+    private static int id(String name, ByteArrayEnumerator names) {
+      return names.enumerate(Convert.string2utf(name));
+    }
+  }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/compiler/CompilerElement.java b/java/java-indexing-impl/src/com/intellij/compiler/CompilerElement.java
new file mode 100644 (file)
index 0000000..361b673
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.compiler;
+
+public abstract class CompilerElement {
+  public static final CompilerElement[] EMPTY_ARRAY = new CompilerElement[0];
+
+  public static class CompilerMethod extends CompilerElement {
+    private final String myJavacClassName;
+    private final String myJavacMethodName;
+    private final int myJavacParameterCount;
+
+    CompilerMethod(String javacClassName, String javacMethodName, int javacParameterCount) {
+      myJavacClassName = javacClassName;
+      myJavacMethodName = javacMethodName;
+      myJavacParameterCount = javacParameterCount;
+    }
+
+    public String getJavacClassName() {
+      return myJavacClassName;
+    }
+
+    public String getJavacMethodName() {
+      return myJavacMethodName;
+    }
+
+    public int getJavacParameterCount() {
+      return myJavacParameterCount;
+    }
+  }
+
+  public static class CompilerClass extends CompilerElement {
+    private final String myJavacName;
+
+    CompilerClass(String javacName) {
+      myJavacName = javacName;
+    }
+
+    public String getJavacName() {
+      return myJavacName;
+    }
+  }
+
+  public static class CompilerField extends CompilerElement {
+    private final String myJavacClassName;
+    private final String myJavacName;
+
+    CompilerField(String javacClassName, String javacName) {
+      myJavacClassName = javacClassName;
+      myJavacName = javacName;
+    }
+
+    public String getJavacClassName() {
+      return myJavacClassName;
+    }
+
+    public String getJavacName() {
+      return myJavacName;
+    }
+  }
+
+  public static class CompilerFunExpr extends CompilerElement {
+    private final String myJavacClassName;
+
+    CompilerFunExpr(String javacClassName) {
+      myJavacClassName = javacClassName;
+    }
+
+    public String getJavacClassName() {
+      return myJavacClassName;
+    }
+  }
+}
index 0b5d252ad6589ad6eca8d654c946c72b76e6ef62..1d30f4a11ce07eb2561a693fd4ed3af1a65e4cab 100644 (file)
@@ -36,7 +36,7 @@ public abstract class CompilerReferenceService extends AbstractProjectComponent
   }
 
   @Nullable
-  public abstract GlobalSearchScope getMayContainReferencesInCodeScope(@NotNull PsiElement element);
+  public abstract GlobalSearchScope getMayContainReferencesInCodeScope(@NotNull PsiElement element, @NotNull CompilerSearchAdapter adapter);
 
   public static boolean isEnabled() {
     return IS_ENABLED_KEY.asBoolean();
similarity index 73%
rename from java/compiler/impl/src/com/intellij/compiler/CompilerReferenceConverter.java
rename to java/java-indexing-impl/src/com/intellij/compiler/CompilerSearchAdapter.java
index 0d4742dc717a3f70775a1ce99905b74ef7991135..e25ff5179c7ecd8202318f701b6285549ae70573 100644 (file)
  */
 package com.intellij.compiler;
 
-import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.psi.PsiElement;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jps.backwardRefs.CompilerElement;
 
-public interface CompilerReferenceConverter {
-  @NotNull
-  FileType getAvailabilitySrcFileType();
+public interface CompilerSearchAdapter {
+
+  boolean needOverrideElement();
 
   @Nullable
-  CompilerElement sourceElementAsCompilerElement(@NotNull PsiElement element);
+  CompilerElement asCompilerElement(@NotNull PsiElement psi);
 
   @NotNull
-  CompilerElement[] libraryElementAsCompilerElements(@NotNull PsiElement element);
+  CompilerElement[] libraryElementAsCompilerElements(@NotNull PsiElement psi);
 }
similarity index 91%
rename from java/compiler/impl/src/com/intellij/compiler/JavaCompilerReferenceConverter.java
rename to java/java-indexing-impl/src/com/intellij/compiler/JavaBaseCompilerSearchAdapter.java
index c06409bd3ee27319ebcd1dbdb7b9ef6e4fcccb4c..21b3c42c8bdd8aac4a0110a6c585519b35378e7f 100644 (file)
  */
 package com.intellij.compiler;
 
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.StdFileTypes;
 import com.intellij.openapi.roots.impl.LibraryScopeCache;
 import com.intellij.psi.*;
 import com.intellij.psi.search.searches.ClassInheritorsSearch;
 import com.intellij.psi.util.ClassUtil;
-import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.Processor;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jps.backwardRefs.CompilerElement;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Function;
 
-public class JavaCompilerReferenceConverter implements CompilerReferenceConverter {
-  @NotNull
+public class JavaBaseCompilerSearchAdapter implements CompilerSearchAdapter {
+  public static final JavaBaseCompilerSearchAdapter INSTANCE = new JavaBaseCompilerSearchAdapter();
+
   @Override
-  public FileType getAvailabilitySrcFileType() {
-    return StdFileTypes.JAVA;
+  public boolean needOverrideElement() {
+    return true;
   }
 
   @Nullable
   @Override
-  public CompilerElement sourceElementAsCompilerElement(@NotNull PsiElement element) {
+  public CompilerElement asCompilerElement(@NotNull PsiElement element) {
     if (mayBeVisibleOutsideOwnerFile(element)) {
       if (element instanceof PsiField) {
         final PsiField field = (PsiField)element;
index 537c2e481fc151a1d5c3e4b06fe712cf31181f0e..409c4dcda36c9072ee1dcf45f88e7398eb89d7a3 100644 (file)
@@ -25,6 +25,6 @@ public class JavaCompilerReferencesInCodeScopeOptimizer implements InCodeScopeOp
   @Nullable
   @Override
   public GlobalSearchScope getOptimizedScopeInCode(@NotNull PsiElement element) {
-    return CompilerReferenceService.getInstance(element.getProject()).getMayContainReferencesInCodeScope(element);
+    return CompilerReferenceService.getInstance(element.getProject()).getMayContainReferencesInCodeScope(element, JavaBaseCompilerSearchAdapter.INSTANCE);
   }
 }
diff --git a/java/java-indexing-impl/src/com/intellij/compiler/JavaFunctionalExpressionCompilerSearchAdapter.java b/java/java-indexing-impl/src/com/intellij/compiler/JavaFunctionalExpressionCompilerSearchAdapter.java
new file mode 100644 (file)
index 0000000..a4a96a5
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.compiler;
+
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.ClassUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class JavaFunctionalExpressionCompilerSearchAdapter implements CompilerSearchAdapter {
+  public static final JavaFunctionalExpressionCompilerSearchAdapter INSTANCE =
+    new JavaFunctionalExpressionCompilerSearchAdapter();
+
+  @Override
+  public boolean needOverrideElement() {
+    return false;
+  }
+
+  @Nullable
+  @Override
+  public CompilerElement asCompilerElement(@NotNull PsiElement psi) {
+    final String qualifiedName = ClassUtil.getJVMClassName((PsiClass)psi);
+    return qualifiedName == null ? null : new CompilerElement.CompilerFunExpr(qualifiedName);
+  }
+
+  @NotNull
+  @Override
+  public CompilerElement[] libraryElementAsCompilerElements(@NotNull PsiElement psi) {
+    return new CompilerElement[] {asCompilerElement(psi)};
+  }
+}
index dee8b64c880e16953c14be8779c5f1df8154209c..bd187a5c7c1a8f160a701f7970309f28d9692bb9 100644 (file)
@@ -15,6 +15,8 @@
  */
 package com.intellij.psi.impl.search;
 
+import com.intellij.compiler.CompilerReferenceService;
+import com.intellij.compiler.JavaFunctionalExpressionCompilerSearchAdapter;
 import com.intellij.lang.injection.InjectedLanguageManager;
 import com.intellij.openapi.application.QueryExecutorBase;
 import com.intellij.openapi.application.ReadAction;
@@ -110,6 +112,14 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
           if (samType == null) continue;
 
           SearchScope scope = samClass.getUseScope().intersectWith(queryParameters.getEffectiveSearchScope());
+
+          final GlobalSearchScope mayContainReferencesScope =
+            CompilerReferenceService.getInstance(project).getMayContainReferencesInCodeScope(samClass,
+                                                                                             JavaFunctionalExpressionCompilerSearchAdapter.INSTANCE);
+          if (mayContainReferencesScope != null) {
+            scope = scope.intersectWith(mayContainReferencesScope);
+          }
+
           descriptors.add(new SamDescriptor(samClass, saMethod, samType, GlobalSearchScopeUtil.toGlobalSearchScope(scope, project)));
         }
       }
diff --git a/java/java-tests/testData/compiler/bytecodeReferences/testLambda/Bar.java b/java/java-tests/testData/compiler/bytecodeReferences/testLambda/Bar.java
new file mode 100644 (file)
index 0000000..7963c52
--- /dev/null
@@ -0,0 +1,5 @@
+class Bar {
+  void m() {
+    Foo f = () -> {};
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/compiler/bytecodeReferences/testLambda/BarRef.java b/java/java-tests/testData/compiler/bytecodeReferences/testLambda/BarRef.java
new file mode 100644 (file)
index 0000000..2e4aa4e
--- /dev/null
@@ -0,0 +1,9 @@
+import java.util.Collections;
+
+class BarRef {
+
+  static void m() {
+    Foo r = Collections::emptyList;
+  }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/compiler/bytecodeReferences/testLambda/Foo.java b/java/java-tests/testData/compiler/bytecodeReferences/testLambda/Foo.java
new file mode 100644 (file)
index 0000000..5970ace
--- /dev/null
@@ -0,0 +1,4 @@
+@FunctionalInterface
+public interface F<caret>oo {
+  void doAction();
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/compiler/bytecodeReferences/testLambda/FooImpl.java b/java/java-tests/testData/compiler/bytecodeReferences/testLambda/FooImpl.java
new file mode 100644 (file)
index 0000000..cc1ea79
--- /dev/null
@@ -0,0 +1,11 @@
+interface FooImpl extends Foo {}
+
+class AAA {
+
+  void m() {
+
+    FooImpl l = () -> {};
+
+  }
+
+}
\ No newline at end of file
index dbf32b5951eabcfc5c82823109808d3f6683bd47..7daff8ab7220516595ddf6867fd5369c9fc49288 100644 (file)
@@ -18,10 +18,12 @@ package com.intellij.compiler;
 import com.intellij.JavaTestUtil;
 import com.intellij.codeInsight.completion.AbstractCompilerAwareTest;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiMember;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.testFramework.SkipSlowTestLocally;
+import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
 import com.intellij.util.containers.ContainerUtil;
 
 import java.util.Set;
@@ -50,27 +52,41 @@ public class CompilerReferencesTest extends AbstractCompilerAwareTest {
 
   public void testIsNotReady() {
     myFixture.configureByFile(getName() + "/Foo.java");
-    assertNull(getReferentFilesForElementUnderCaret());
+    assertNull(getReferentFilesForElementUnderCaret(JavaBaseCompilerSearchAdapter.INSTANCE));
   }
 
   public void testSimpleUsagesInFullyCompiledProject() {
     myFixture.configureByFiles(getName() + "/Foo.java", getName() + "/Bar.java", getName() + "/Baz.java", getName() + "/FooImpl.java");
     rebuildProject();
 
-    final Set<VirtualFile> referents = getReferentFilesForElementUnderCaret();
+    final Set<VirtualFile> referents = getReferentFilesForElementUnderCaret(JavaBaseCompilerSearchAdapter.INSTANCE);
     assertNotNull(referents);
     final Set<String> filesWithReferences = referents.stream().map(VirtualFile::getName).collect(Collectors.toSet());
 
     assertEquals(filesWithReferences, ContainerUtil.set("Baz.java", "Foo.java", "FooImpl.java"));
     myFixture.addFileToProject("SomeModification.java", "");
-    assertNull(getReferentFilesForElementUnderCaret());
+    assertNull(getReferentFilesForElementUnderCaret(JavaBaseCompilerSearchAdapter.INSTANCE));
   }
 
-  private Set<VirtualFile> getReferentFilesForElementUnderCaret() {
+  public void testLambda() {
+    myFixture.configureByFiles(getName() + "/Foo.java", getName() + "/FooImpl.java", getName() + "/Bar.java", getName() + "/BarRef.java");
+    rebuildProject();
+    final Set<VirtualFile> referents = getReferentFilesForElementUnderCaret(JavaFunctionalExpressionCompilerSearchAdapter.INSTANCE);
+    assertNotNull(referents);
+    final Set<String> filesWithReferences = referents.stream().map(VirtualFile::getName).collect(Collectors.toSet());
+    assertEquals(filesWithReferences, ContainerUtil.set("Bar.java", "BarRef.java"));
+  }
+
+  private Set<VirtualFile> getReferentFilesForElementUnderCaret(CompilerSearchAdapter adapter) {
     final PsiElement atCaret = myFixture.getElementAtCaret();
     assertNotNull(atCaret);
     final PsiMember memberAtCaret = PsiTreeUtil.getParentOfType(atCaret, PsiMember.class, false);
     assertNotNull(memberAtCaret);
-    return ((CompilerReferenceServiceImpl)CompilerReferenceService.getInstance(myFixture.getProject())).getReferentFiles(memberAtCaret);
+    return ((CompilerReferenceServiceImpl)CompilerReferenceService.getInstance(myFixture.getProject())).getReferentFiles(memberAtCaret, adapter);
+  }
+
+  @Override
+  protected void tuneFixture(JavaModuleFixtureBuilder moduleBuilder) throws Exception {
+    moduleBuilder.setLanguageLevel(LanguageLevel.JDK_1_8);
   }
 }
diff --git a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/CompilerElement.java b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/CompilerElement.java
deleted file mode 100644 (file)
index 4e91a47..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2000-2016 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jetbrains.jps.backwardRefs;
-
-import com.sun.tools.javac.util.Convert;
-import org.jetbrains.annotations.NotNull;
-
-public abstract class CompilerElement {
-  public static final CompilerElement[] EMPTY_ARRAY = new CompilerElement[0];
-
-  @NotNull
-  public abstract LightUsage asUsage(ByteArrayEnumerator byteArrayEnumerator);
-
-  public static class CompilerMethod extends CompilerElement {
-    private final byte[] myJavacClassName;
-    private final byte[] myJavacMethodName;
-    private final int myJavacParameterCount;
-
-    public CompilerMethod(String javacClassName, String javacMethodName, int count) {
-      this(bytes(javacClassName), bytes(javacMethodName), count);
-    }
-
-    CompilerMethod(byte[] javacClassName, byte[] javacMethodName, int javacParameterCount) {
-      myJavacClassName = javacClassName;
-      myJavacMethodName = javacMethodName;
-      myJavacParameterCount = javacParameterCount;
-    }
-
-    @NotNull
-    @Override
-    public LightUsage asUsage(ByteArrayEnumerator byteArrayEnumerator) {
-      return new LightUsage.LightMethodUsage(byteArrayEnumerator.enumerate(myJavacClassName),
-                                             byteArrayEnumerator.enumerate(myJavacMethodName),
-                                             myJavacParameterCount);
-    }
-  }
-
-  public static class CompilerClass extends CompilerElement {
-    private final byte[] myJavacName;
-
-    public CompilerClass(String name) {
-      this(bytes(name));
-    }
-
-    CompilerClass(byte[] javacName) {
-      myJavacName = javacName;
-    }
-
-    @NotNull
-    @Override
-    public LightUsage asUsage(ByteArrayEnumerator byteArrayEnumerator) {
-      return new LightUsage.LightClassUsage(byteArrayEnumerator.enumerate(myJavacName));
-    }
-  }
-
-  public static class CompilerField extends CompilerElement {
-    private final byte[] myJavacClassName;
-    private final byte[] myJavacName;
-
-    public CompilerField(String javacClassName, String name) {
-      this(bytes(javacClassName), bytes(name));
-    }
-
-    CompilerField(byte[] javacClassName, byte[] javacName) {
-      myJavacClassName = javacClassName;
-      myJavacName = javacName;
-    }
-
-    @NotNull
-    @Override
-    public LightUsage asUsage(ByteArrayEnumerator byteArrayEnumerator) {
-      return new LightUsage.LightFieldUsage(byteArrayEnumerator.enumerate(myJavacClassName),
-                                            byteArrayEnumerator.enumerate(myJavacName));
-    }
-  }
-
-  static byte[] bytes(String str) {
-    //TODO
-    return Convert.string2utf(str);
-  }
-}
index ebd4cfdcd0ce78664cc70f63a3f34f21263ae7d1..29886eb35d4636df732f10b063ba14dd282f3027 100644 (file)
@@ -71,7 +71,7 @@ public abstract class LightUsage implements RW.Savable {
     private final int myName;
     private final int myParameterCount;
 
-    LightMethodUsage(int owner, int name, int parameterCount) {
+    public LightMethodUsage(int owner, int name, int parameterCount) {
       super(owner);
       myName = name;
       myParameterCount = parameterCount;
@@ -130,7 +130,7 @@ public abstract class LightUsage implements RW.Savable {
   public static class LightFieldUsage extends LightUsage {
     private final int myName;
 
-    LightFieldUsage(int owner, int name) {
+    public LightFieldUsage(int owner, int name) {
       super(owner);
       myName = name;
     }
@@ -178,7 +178,7 @@ public abstract class LightUsage implements RW.Savable {
   }
 
   public static class LightClassUsage extends LightUsage {
-    LightClassUsage(int owner) {
+    public LightClassUsage(int owner) {
       super(owner);
     }