javac ast indices: search for lambda expressions; version #2 (with lambda hierarchy)
authorDmitry Batkovich <dmitry.batkovich@jetbrains.com>
Mon, 17 Oct 2016 15:26:29 +0000 (18:26 +0300)
committerDmitry Batkovich <dmitry.batkovich@jetbrains.com>
Mon, 17 Oct 2016 15:27:26 +0000 (18:27 +0300)
32 files changed:
java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerHierarchyInfoImpl.java [new file with mode: 0644]
java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerHierarchySearchType.java [new file with mode: 0644]
java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerReferenceReader.java
java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerReferenceServiceImpl.java
java/compiler/impl/src/com/intellij/compiler/backwardRefs/DirtyModulesHolder.java [new file with mode: 0644]
java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaCompilerElementRetriever.java [moved from java/java-indexing-impl/src/com/intellij/compiler/JavaBaseCompilerSearchAdapter.java with 52% similarity]
java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaLightUsageAdapter.java [new file with mode: 0644]
java/compiler/impl/src/com/intellij/compiler/backwardRefs/LanguageLightRefAdapter.java [new file with mode: 0644]
java/compiler/impl/src/com/intellij/compiler/backwardRefs/LanguageLightUsageConverter.java [deleted file]
java/java-indexing-impl/src/com/intellij/compiler/ClassResolvingCompilerSearchAdapter.java [deleted file]
java/java-indexing-impl/src/com/intellij/compiler/CompilerDirectHierarchyInfo.java [moved from java/java-indexing-impl/src/com/intellij/compiler/CompilerSearchAdapter.java with 50% similarity]
java/java-indexing-impl/src/com/intellij/compiler/CompilerElement.java [deleted file]
java/java-indexing-impl/src/com/intellij/compiler/CompilerReferenceService.java
java/java-indexing-impl/src/com/intellij/compiler/JavaCompilerReferencesCodeUsageScopeOptimizer.java
java/java-indexing-impl/src/com/intellij/compiler/JavaFunctionalExpressionCompilerSearchAdapter.java [deleted file]
java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java
java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaFunctionalExpressionSearcher.java
java/java-tests/testData/compiler/bytecodeReferences/testInnerFunExpressions/Foo.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/compiler/CompilerReferencesTest.java
jps/javac-ref-scanner-8/src/org/jetbrains/jps/javac/ast/Javac8RefScanner.java
jps/javac-ref-scanner-8/testData/referenceIndex/lambda/initialIndex.txt
jps/javac-ref-scanner-8/testData/referenceIndex/methodReference/initialIndex.txt
jps/jps-builders/src/org/jetbrains/jps/backwardRefs/BackwardReferenceIndexWriter.java
jps/jps-builders/src/org/jetbrains/jps/backwardRefs/BackwardReferenceRegistrar.java
jps/jps-builders/src/org/jetbrains/jps/backwardRefs/ByteArrayEnumerator.java
jps/jps-builders/src/org/jetbrains/jps/backwardRefs/CompilerBackwardReferenceIndex.java
jps/jps-builders/src/org/jetbrains/jps/backwardRefs/LightRef.java [new file with mode: 0644]
jps/jps-builders/src/org/jetbrains/jps/backwardRefs/LightRefDescriptor.java [new file with mode: 0644]
jps/jps-builders/src/org/jetbrains/jps/backwardRefs/LightUsage.java [deleted file]
jps/jps-builders/src/org/jetbrains/jps/javac/ast/JavacReferencesCollector.java
jps/jps-builders/src/org/jetbrains/jps/javac/ast/api/JavacFileReferencesRegistrar.java
jps/jps-builders/testSrc/org/jetbrains/references/ReferenceIndexTestBase.kt

diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerHierarchyInfoImpl.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerHierarchyInfoImpl.java
new file mode 100644 (file)
index 0000000..a9138c6
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.CompilerDirectHierarchyInfo;
+import com.intellij.openapi.util.Couple;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+import java.util.stream.Stream;
+
+class CompilerHierarchyInfoImpl<T extends PsiElement> implements CompilerDirectHierarchyInfo<T> {
+  private final GlobalSearchScope myDirtyScope;
+  private final GlobalSearchScope mySearchScope;
+  private Couple<Map<VirtualFile, T[]>> myCandidatePerFile;
+
+  CompilerHierarchyInfoImpl(Couple<Map<VirtualFile, T[]>> candidatePerFile,
+                            GlobalSearchScope dirtyScope,
+                            GlobalSearchScope searchScope) {
+    myCandidatePerFile = candidatePerFile;
+    myDirtyScope = dirtyScope;
+    mySearchScope = searchScope;
+  }
+
+  @Override
+  @NotNull
+  public Stream<T> getHierarchyChildren() {
+    return selectClassesInScope(myCandidatePerFile.getFirst(), mySearchScope);
+  }
+
+  @Override
+  @NotNull
+  public Stream<T> getHierarchyChildCandidates() {
+    return selectClassesInScope(myCandidatePerFile.getSecond(), mySearchScope);
+  }
+
+  @Override
+  @NotNull
+  public GlobalSearchScope getDirtyScope() {
+    return myDirtyScope;
+  }
+
+  private static <T extends PsiElement> Stream<T> selectClassesInScope(Map<VirtualFile, T[]> classesPerFile, GlobalSearchScope searchScope) {
+    return classesPerFile.entrySet().stream().filter(e -> searchScope.contains(e.getKey())).flatMap(e -> Stream.of(e.getValue()));
+  }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerHierarchySearchType.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerHierarchySearchType.java
new file mode 100644 (file)
index 0000000..7a19a62
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.impl.source.PsiFileWithStubSupport;
+import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator;
+import org.jetbrains.jps.backwardRefs.LightRef;
+
+import java.util.Collection;
+
+enum CompilerHierarchySearchType {
+  DIRECT_INHERITOR {
+    @Override
+    <T extends PsiElement> T[] performSearchInFile(Collection<LightRef> definitions,
+                                                   PsiNamedElement baseElement,
+                                                   ByteArrayEnumerator nameEnumerator,
+                                                   PsiFileWithStubSupport file,
+                                                   LanguageLightRefAdapter adapter) {
+      return (T[])adapter.findDirectInheritorCandidatesInFile(definitions, nameEnumerator, file, baseElement);
+    }
+
+    @Override
+    Class<? extends LightRef> getRequiredClass(LanguageLightRefAdapter<?, ?> adapter) {
+      return adapter.getHierarchyObjectClass();
+    }
+  },
+  FUNCTIONAL_EXPRESSION {
+    @Override
+    <T extends PsiElement> T[] performSearchInFile(Collection<LightRef> definitions,
+                                                   PsiNamedElement baseElement,
+                                                   ByteArrayEnumerator nameEnumerator,
+                                                   PsiFileWithStubSupport file,
+                                                   LanguageLightRefAdapter adapter) {
+      return (T[])adapter.findFunExpressionsInFile(definitions, file);
+    }
+
+    @Override
+    Class<? extends LightRef> getRequiredClass(LanguageLightRefAdapter<?, ?> adapter) {
+      return adapter.getFunExprClass();
+    }
+  };
+
+  abstract <T extends PsiElement> T[] performSearchInFile(Collection<LightRef> definitions,
+                                                          PsiNamedElement baseElement,
+                                                          ByteArrayEnumerator nameEnumerator,
+                                                          PsiFileWithStubSupport file,
+                                                          LanguageLightRefAdapter adapter);
+
+  abstract Class<? extends LightRef> getRequiredClass(LanguageLightRefAdapter<?, ?> adapter);
+}
index 995ae637a85364991d4cfe46e6ba9edce600ac24..2c21dde2bf7819447763eec38ad224e79ab9b76c 100644 (file)
  */
 package com.intellij.compiler.backwardRefs;
 
-import com.intellij.compiler.ClassResolvingCompilerSearchAdapter;
-import com.intellij.compiler.CompilerElement;
-import com.intellij.compiler.CompilerSearchAdapter;
 import com.intellij.compiler.server.BuildManager;
-import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.application.ReadAction;
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Couple;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileWithId;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiManager;
 import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.impl.source.PsiFileWithStubSupport;
 import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.util.ObjectUtils;
-import com.intellij.util.SmartList;
 import com.intellij.util.containers.Queue;
-import com.sun.tools.javac.util.Convert;
 import gnu.trove.THashMap;
 import gnu.trove.THashSet;
 import gnu.trove.TIntHashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator;
 import org.jetbrains.jps.backwardRefs.CompilerBackwardReferenceIndex;
-import org.jetbrains.jps.backwardRefs.LightUsage;
+import org.jetbrains.jps.backwardRefs.LightRef;
 
 import java.io.File;
 import java.io.IOException;
@@ -47,8 +45,6 @@ import java.util.*;
 import static java.util.stream.Collectors.*;
 
 class CompilerReferenceReader {
-  private final static Logger LOG = Logger.getInstance(CompilerReferenceReader.class);
-
   private final CompilerBackwardReferenceIndex myIndex;
 
   private CompilerReferenceReader(File buildDir) throws IOException {
@@ -56,21 +52,16 @@ class CompilerReferenceReader {
   }
 
   @Nullable
-  TIntHashSet findReferentFileIds(@NotNull CompilerElement element,
-                                         @NotNull CompilerSearchAdapter adapter,
-                                         boolean checkBaseClassAmbiguity) {
-    LightUsage usage = asLightUsage(element);
-
+  TIntHashSet findReferentFileIds(@NotNull LightRef ref, boolean checkBaseClassAmbiguity) {
+    LightRef.LightClassHierarchyElementDef hierarchyElement = ref instanceof LightRef.LightClassHierarchyElementDef ?
+                                                              (LightRef.LightClassHierarchyElementDef)ref :
+                                                              ((LightRef.LightMember)ref).getOwner();
     TIntHashSet set = new TIntHashSet();
-    if (adapter.needOverrideElement()) {
-      final LightUsage[] hierarchy = getWholeHierarchy(usage.getOwner(), checkBaseClassAmbiguity);
-      if (hierarchy == null) return null;
-      for (LightUsage aClass : hierarchy) {
-        final LightUsage overriderUsage = usage.override(aClass);
-        addUsages(overriderUsage, set);
-      }
-    } else {
-      addUsages(usage, set);
+    final LightRef.NamedLightRef[] hierarchy = getWholeHierarchy(hierarchyElement, checkBaseClassAmbiguity);
+    if (hierarchy == null) return null;
+    for (LightRef.NamedLightRef aClass : hierarchy) {
+      final LightRef overriderUsage = aClass.override(aClass.getName());
+      addUsages(overriderUsage, set);
     }
     return set;
   }
@@ -82,56 +73,63 @@ class CompilerReferenceReader {
    * 2nd map: candidates. One need to check that these classes are really direct inheritors
    */
   @Nullable
-  <T extends PsiNamedElement> Couple<Map<VirtualFile, T[]>> getDirectInheritors(@NotNull PsiNamedElement baseClass,
-                                                                                @Nullable CompilerReferenceServiceImpl.CompilerElementInfo classSearchElementInfo,
-                                                                                @NotNull ClassResolvingCompilerSearchAdapter<T> inheritorSearchAdapter,
-                                                                                @NotNull GlobalSearchScope searchScope,
-                                                                                @NotNull GlobalSearchScope dirtyScope,
-                                                                                @NotNull Project project,
-                                                                                @NotNull FileType fileType) {
-    if (classSearchElementInfo == null) return null;
-    LOG.assertTrue(classSearchElementInfo.searchElements.length == 1);
-
-    Collection<CompilerBackwardReferenceIndex.LightDefinition> candidates = myIndex.getBackwardHierarchyMap().get(asLightUsage(classSearchElementInfo.searchElements[0]));
+  <T extends PsiElement> Couple<Map<VirtualFile, T[]>> getDirectInheritors(@NotNull PsiNamedElement baseClass,
+                                                                           @NotNull LightRef searchElement,
+                                                                           @NotNull GlobalSearchScope searchScope,
+                                                                           @NotNull GlobalSearchScope dirtyScope,
+                                                                           @NotNull Project project,
+                                                                           @NotNull FileType fileType,
+                                                                           @NotNull CompilerHierarchySearchType searchType) {
+    Collection<CompilerBackwardReferenceIndex.LightDefinition> candidates = myIndex.getBackwardHierarchyMap().get(searchElement);
     if (candidates == null) return Couple.of(Collections.emptyMap(), Collections.emptyMap());
 
-    Set<Class<? extends LightUsage>> suitableClasses = new THashSet<>();
-    for (LanguageLightUsageConverter converter : LanguageLightUsageConverter.INSTANCES) {
-      if (fileType == converter.getFileSourceType()) {
-        suitableClasses.addAll(converter.getLanguageLightUsageClasses());
-        break;
-      }
-    }
-
-    final GlobalSearchScope effectiveSearchScope = GlobalSearchScope.notScope(dirtyScope).intersectWith(searchScope);
-
-    Map<VirtualFile, SmartList<String>> candidatesPerFile = candidates
+    GlobalSearchScope effectiveSearchScope = GlobalSearchScope.notScope(dirtyScope).intersectWith(searchScope);
+    LanguageLightRefAdapter adapter = CompilerReferenceServiceImpl.findAdapterForFileType(fileType);
+    Class<? extends LightRef> requiredLightRefClass = searchType.getRequiredClass(adapter);
+    Map<VirtualFile, List<LightRef>> candidatesPerFile = candidates
       .stream()
-      .filter(def -> suitableClasses.contains(def.getUsage().getClass()))
+      .filter(def -> requiredLightRefClass.isInstance(def.getRef()))
       .map(definition -> {
         final VirtualFile file = findFile(definition.getFileId());
-        return file != null && effectiveSearchScope.contains(file) ? new DecodedInheritorCandidate(getName(definition), file) : null;
+        if (file != null && effectiveSearchScope.contains(file)) {
+          return new Object() {
+            final VirtualFile containingFile = file;
+            final LightRef def = definition.getRef();
+          };
+        }
+        else {
+          return null;
+        }
       })
       .filter(Objects::nonNull)
-      .collect(groupingBy(DecodedInheritorCandidate::getDeclarationFile, mapping(DecodedInheritorCandidate::getQName, toCollection(SmartList::new))));
+      .collect(groupingBy(x -> x.containingFile, mapping(x -> x.def, toList())));
 
     if (candidatesPerFile.isEmpty()) return Couple.of(Collections.emptyMap(), Collections.emptyMap());
 
     Map<VirtualFile, T[]> inheritors = new THashMap<>(candidatesPerFile.size());
     Map<VirtualFile, T[]> inheritorCandidates = new THashMap<>();
 
-    candidatesPerFile.forEach((file, directInheritors) -> {
-      final T[] currInheritors = inheritorSearchAdapter.getCandidatesFromFile(directInheritors, baseClass, file, project);
+    final PsiManager psiManager = ReadAction.compute(() -> PsiManager.getInstance(project));
+
+    candidatesPerFile.forEach((file, directInheritors) -> ReadAction.run(() -> {
+      final PsiFileWithStubSupport psiFile = (PsiFileWithStubSupport)ReadAction.compute(() -> psiManager.findFile(file));
+      final T[] currInheritors = searchType.performSearchInFile(directInheritors, baseClass, myIndex.getByteSeqEum(), psiFile, adapter);
       if (currInheritors.length == directInheritors.size()) {
         inheritors.put(file, currInheritors);
-      } else {
+      }
+      else {
         inheritorCandidates.put(file, currInheritors);
       }
-    });
+    }));
 
     return Couple.of(inheritors, inheritorCandidates);
   }
 
+  @NotNull
+  ByteArrayEnumerator getNameEnumerator() {
+    return myIndex.getByteSeqEum();
+  }
+
   void close() {
     myIndex.close();
   }
@@ -149,7 +147,7 @@ class CompilerReferenceReader {
     }
   }
 
-  private void addUsages(LightUsage usage, TIntHashSet sink) {
+  private void addUsages(LightRef usage, TIntHashSet sink) {
     final Collection<Integer> usageFiles = myIndex.getBackwardReferenceMap().get(usage);
     if (usageFiles != null) {
       for (int fileId : usageFiles) {
@@ -161,19 +159,6 @@ class CompilerReferenceReader {
     }
   }
 
-  @NotNull
-  private LightUsage asLightUsage(@NotNull CompilerElement element) {
-    LightUsage usage = null;
-    for (LanguageLightUsageConverter converter : LanguageLightUsageConverter.INSTANCES) {
-      usage = converter.asLightUsage(element, myIndex.getByteSeqEum());
-      if (usage != null) {
-        break;
-      }
-    }
-    LOG.assertTrue(usage != null);
-    return usage;
-  }
-
   private VirtualFile findFile(int id) {
     try {
       String path = myIndex.getFilePathEnumerator().valueOf(id);
@@ -186,14 +171,14 @@ class CompilerReferenceReader {
   }
 
   @Nullable("return null if the class hierarchy contains ambiguous qualified names")
-  private LightUsage[] getWholeHierarchy(LightUsage aClass, boolean checkBaseClassAmbiguity) {
-    Set<LightUsage> result = new THashSet<>();
-    Queue<LightUsage> q = new Queue<>(10);
-    q.addLast(aClass);
+  private LightRef.NamedLightRef[] getWholeHierarchy(LightRef.LightClassHierarchyElementDef hierarchyElement, boolean checkBaseClassAmbiguity) {
+    Set<LightRef.NamedLightRef> result = new THashSet<>();
+    Queue<LightRef.NamedLightRef> q = new Queue<>(10);
+    q.addLast(hierarchyElement);
     while (!q.isEmpty()) {
-      LightUsage curClass = q.pullFirst();
+      LightRef.NamedLightRef curClass = q.pullFirst();
       if (result.add(curClass)) {
-        if (checkBaseClassAmbiguity || curClass != aClass) {
+        if (checkBaseClassAmbiguity || curClass != hierarchyElement) {
           final Collection<Integer> definitionFiles = myIndex.getBackwardClassDefinitionMap().get(curClass);
           if (definitionFiles.size() != 1) {
             return null;
@@ -202,39 +187,14 @@ class CompilerReferenceReader {
         final Collection<CompilerBackwardReferenceIndex.LightDefinition> subClassDefs = myIndex.getBackwardHierarchyMap().get(curClass);
         if (subClassDefs != null) {
           for (CompilerBackwardReferenceIndex.LightDefinition subclass : subClassDefs) {
-            q.addLast(subclass.getUsage());
+            final LightRef ref = subclass.getRef();
+            if (ref instanceof LightRef.LightClassHierarchyElementDef) {
+              q.addLast((LightRef.LightClassHierarchyElementDef) ref);
+            }
           }
         }
       }
     }
-    return result.toArray(new LightUsage[result.size()]);
-  }
-
-  @NotNull
-  private String getName(CompilerBackwardReferenceIndex.LightDefinition def) {
-    try {
-      return Convert.utf2string(ObjectUtils.notNull(myIndex.getByteSeqEum().valueOf(def.getUsage().getName())));
-    }
-    catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  private static class DecodedInheritorCandidate {
-    private final String qName;
-    private final VirtualFile declarationFile;
-
-    private DecodedInheritorCandidate(String name, VirtualFile file) {
-      qName = name;
-      declarationFile = file;
-    }
-
-    public VirtualFile getDeclarationFile() {
-      return declarationFile;
-    }
-
-    public String getQName() {
-      return qName;
-    }
+    return result.toArray(new LightRef.NamedLightRef[result.size()]);
   }
 }
\ No newline at end of file
index 9900e1fd81257a3bc6caf32eae1c1d4c91747421..7cf8a437061dfde9d7336c58ee9ed60ecef73bd7 100644 (file)
  */
 package com.intellij.compiler.backwardRefs;
 
-import com.intellij.compiler.ClassResolvingCompilerSearchAdapter;
-import com.intellij.compiler.CompilerElement;
+import com.intellij.compiler.CompilerDirectHierarchyInfo;
 import com.intellij.compiler.CompilerReferenceService;
-import com.intellij.compiler.CompilerSearchAdapter;
 import com.intellij.compiler.server.BuildManager;
 import com.intellij.compiler.server.BuildManagerListener;
 import com.intellij.lang.injection.InjectedLanguageManager;
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.ReadAction;
 import com.intellij.openapi.compiler.*;
 import com.intellij.openapi.fileTypes.FileType;
@@ -35,8 +34,8 @@ import com.intellij.openapi.roots.ProjectRootManager;
 import com.intellij.openapi.roots.impl.LibraryScopeCache;
 import com.intellij.openapi.util.Couple;
 import com.intellij.openapi.util.ModificationTracker;
-import com.intellij.openapi.util.UserDataHolderBase;
-import com.intellij.openapi.vfs.*;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileWithId;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiNamedElement;
 import com.intellij.psi.search.GlobalSearchScope;
@@ -45,25 +44,23 @@ import com.intellij.psi.util.CachedValuesManager;
 import com.intellij.psi.util.PsiModificationTracker;
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.util.containers.ConcurrentFactoryMap;
-import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.indexing.FileBasedIndex;
 import gnu.trove.THashSet;
 import gnu.trove.TIntHashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
+import org.jetbrains.jps.backwardRefs.LightRef;
 
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
 import java.util.concurrent.atomic.LongAdder;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import static com.intellij.psi.search.GlobalSearchScope.*;
+import static com.intellij.psi.search.GlobalSearchScope.getScopeRestrictedByFileTypes;
+import static com.intellij.psi.search.GlobalSearchScope.notScope;
 
 public class CompilerReferenceServiceImpl extends CompilerReferenceService implements ModificationTracker {
   private final Set<FileType> myFileTypes;
@@ -79,11 +76,9 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
   public CompilerReferenceServiceImpl(Project project) {
     super(project);
 
-    myDirtyModulesHolder = new DirtyModulesHolder();
     myProjectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
-    myFileTypes = Collections.unmodifiableSet(Stream.of(LanguageLightUsageConverter.INSTANCES)
-                                                    .map(LanguageLightUsageConverter::getFileSourceType)
-                                                    .collect(Collectors.toSet()));
+    myFileTypes = Stream.of(LanguageLightRefAdapter.INSTANCES).flatMap(a -> a.getFileTypes().stream()).collect(Collectors.toSet());
+    myDirtyModulesHolder = new DirtyModulesHolder(this);
   }
 
   @Override
@@ -110,7 +105,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
         }
 
         private void compilationFinished(int errors, CompileContext context) {
-          BuildManager.getInstance().runCommand(() -> {
+          Runnable compilationFinished = () -> {
             final Module[] compilationModules = context.getCompileScope().getAffectedModules();
             Set<Module> modulesWithErrors;
             if (errors != 0) {
@@ -131,52 +126,12 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
 
             myCompilationCount.increment();
             openReaderIfNeed();
-          });
+          };
+          executeOnBuildThread(compilationFinished);
         }
       });
 
-      VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() {
-        @Override
-        public void fileCreated(@NotNull VirtualFileEvent event) {
-          processChange(event.getFile());
-        }
-
-        @Override
-        public void fileCopied(@NotNull VirtualFileCopyEvent event) {
-          processChange(event.getFile());
-        }
-
-        @Override
-        public void fileMoved(@NotNull VirtualFileMoveEvent event) {
-          processChange(event.getFile());
-        }
-
-        @Override
-        public void beforePropertyChange(@NotNull VirtualFilePropertyEvent event) {
-          if (VirtualFile.PROP_NAME.equals(event.getPropertyName()) || VirtualFile.PROP_SYMLINK_TARGET.equals(event.getPropertyName())) {
-            processChange(event.getFile());
-          }
-        }
-
-        @Override
-        public void beforeContentsChange(@NotNull VirtualFileEvent event) {
-          processChange(event.getFile());
-        }
-
-        @Override
-        public void beforeFileDeletion(@NotNull VirtualFileEvent event) {
-          processChange(event.getFile());
-        }
-
-        @Override
-        public void beforeFileMovement(@NotNull VirtualFileMoveEvent event) {
-          processChange(event.getFile());
-        }
-
-        private void processChange(VirtualFile file) {
-          myDirtyModulesHolder.fileChanged(file);
-        }
-      }, myProject);
+      myDirtyModulesHolder.installVFSListener();
 
       ProgressManager.getInstance().run(new Task.Backgroundable(myProject, CompilerBundle.message("compiler.ref.service.validation.task.name")) {
           @Override
@@ -184,7 +139,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
             indicator.setText(CompilerBundle.message("compiler.ref.service.validation.progress.text"));
             CompileScope projectCompileScope = compilerManager.createProjectCompileScope(myProject);
             boolean isUpToDate = compilerManager.isUpToDate(projectCompileScope);
-            BuildManager.getInstance().runCommand(() -> {
+            executeOnBuildThread(() -> {
               if (isUpToDate) {
                 myDirtyModulesHolder.compilerActivityFinished(projectCompileScope.getAffectedModules(), Module.EMPTY_ARRAY);
                 myCompilationCount.increment();
@@ -206,76 +161,91 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
 
   @Nullable
   @Override
-  public GlobalSearchScope getScopeWithoutCodeReferences(@NotNull PsiElement element, @NotNull CompilerSearchAdapter adapter) {
+  public GlobalSearchScope getScopeWithoutCodeReferences(@NotNull PsiElement element) {
     if (!isServiceEnabledFor(element)) return null;
 
     return CachedValuesManager.getCachedValue(element,
-                                              () -> CachedValueProvider.Result.create(new ConcurrentFactoryMap<CompilerSearchAdapter, GlobalSearchScope>() {
-                                                  @Nullable
-                                                  @Override
-                                                  protected GlobalSearchScope create(CompilerSearchAdapter key) {
-                                                    return calculateScopeWithoutReferences(element, key);
-                                                  }
-                                              },
-                                              PsiModificationTracker.MODIFICATION_COUNT, this)).get(adapter);
+                                              () -> CachedValueProvider.Result.create(calculateScopeWithoutReferences(element),
+                                                                                      PsiModificationTracker.MODIFICATION_COUNT,
+                                                                                      this));
   }
 
   @Nullable
   @Override
-  public <T extends PsiNamedElement> CompilerDirectInheritorInfo<T> getDirectInheritors(@NotNull PsiNamedElement aClass,
-                                                                                         @NotNull GlobalSearchScope useScope,
-                                                                                         @NotNull GlobalSearchScope searchScope,
-                                                                                         @NotNull ClassResolvingCompilerSearchAdapter<T> inheritorSearchAdapter,
-                                                                                         @NotNull FileType searchFileType) {
-    if (!isServiceEnabledFor(aClass) || searchScope == LibraryScopeCache.getInstance(myProject).getLibrariesOnlyScope()) return null;
+  public <T extends PsiElement> CompilerDirectHierarchyInfo<T> getDirectInheritors(@NotNull PsiNamedElement aClass,
+                                                                                   @NotNull GlobalSearchScope useScope,
+                                                                                   @NotNull GlobalSearchScope searchScope,
+                                                                                   @NotNull FileType searchFileType) {
+    return getHierarchyInfo(aClass, useScope, searchScope, searchFileType, CompilerHierarchySearchType.DIRECT_INHERITOR);
+  }
+
+  @Nullable
+  @Override
+  public <T extends PsiElement> CompilerDirectHierarchyInfo<T> getFunExpressions(@NotNull PsiNamedElement functionalInterface,
+                                                                                 @NotNull GlobalSearchScope useScope,
+                                                                                 @NotNull GlobalSearchScope searchScope,
+                                                                                 @NotNull FileType searchFileType) {
+    return getHierarchyInfo(functionalInterface, useScope, searchScope, searchFileType, CompilerHierarchySearchType.FUNCTIONAL_EXPRESSION);
+  }
+
+  @Nullable
+  private <T extends PsiElement> CompilerDirectHierarchyInfo<T> getHierarchyInfo(@NotNull PsiNamedElement aClass,
+                                                                                 @NotNull GlobalSearchScope useScope,
+                                                                                 @NotNull GlobalSearchScope searchScope,
+                                                                                 @NotNull FileType searchFileType,
+                                                                                 @NotNull CompilerHierarchySearchType searchType) {
+      if (!isServiceEnabledFor(aClass) || searchScope == LibraryScopeCache.getInstance(myProject).getLibrariesOnlyScope()) return null;
 
     Couple<Map<VirtualFile, T[]>> directInheritorsAndCandidates =
-      CachedValuesManager.getCachedValue(aClass, () -> CachedValueProvider.Result.create(calculateDirectInheritors(aClass,
-                                                                                                                   inheritorSearchAdapter,
-                                                                                                                   useScope,
-                                                                                                                   searchFileType),
-                                                                                       PsiModificationTracker.MODIFICATION_COUNT,
-                                                                                       this));
+      CachedValuesManager.getCachedValue(aClass, () -> CachedValueProvider.Result.create(
+        new ConcurrentFactoryMap<HierarchySearchKey, Couple<Map<VirtualFile, T[]>>>() {
+        @Nullable
+        @Override
+        protected Couple<Map<VirtualFile, T[]>> create(HierarchySearchKey key) {
+          return calculateDirectInheritors(aClass,
+                                           useScope,
+                                           key.mySearchFileType,
+                                           key.mySearchType);
+        }
+      }, PsiModificationTracker.MODIFICATION_COUNT, this)).get(new HierarchySearchKey(searchType, searchFileType));
 
     if (directInheritorsAndCandidates == null) return null;
     GlobalSearchScope dirtyScope = myDirtyModulesHolder.getDirtyScope();
     if (ElementPlace.LIB == ElementPlace.get(aClass.getContainingFile().getVirtualFile(), myProjectFileIndex)) {
       dirtyScope = dirtyScope.union(LibraryScopeCache.getInstance(myProject).getLibrariesOnlyScope());
     }
-    return new CompilerDirectInheritorInfoImpl<>(directInheritorsAndCandidates, dirtyScope, searchScope);
+    return new CompilerHierarchyInfoImpl<>(directInheritorsAndCandidates, dirtyScope, searchScope);
   }
 
   private boolean isServiceEnabledFor(PsiElement element) {
-    return isServiceEnabled() && !InjectedLanguageManager.getInstance(myProject).isInjectedFragment(ReadAction.compute(() -> element.getContainingFile()));
+    return isServiceEnabled() && !InjectedLanguageManager.getInstance(myProject).isInjectedFragment(element.getContainingFile());
   }
 
   private boolean isServiceEnabled() {
     return myReader != null && isEnabled();
   }
 
-  private <T extends PsiNamedElement> Couple<Map<VirtualFile, T[]>> calculateDirectInheritors(@NotNull PsiNamedElement aClass,
-                                                                                              @NotNull ClassResolvingCompilerSearchAdapter<T> searchAdapter,
-                                                                                              @NotNull GlobalSearchScope useScope,
-                                                                                              @NotNull FileType searchFileType) {
-    final CompilerElementInfo searchElementInfo = asCompilerElements(aClass, searchAdapter, false);
+  private <T extends PsiElement> Couple<Map<VirtualFile, T[]>> calculateDirectInheritors(@NotNull PsiNamedElement aClass,
+                                                                                         @NotNull GlobalSearchScope useScope,
+                                                                                         @NotNull FileType searchFileType,
+                                                                                         @NotNull CompilerHierarchySearchType searchType) {
+
+    final CompilerElementInfo searchElementInfo = asCompilerElements(aClass, false);
+    if (searchElementInfo == null) return null;
+    LightRef searchElement = searchElementInfo.searchElements[0];
+
     myReadDataLock.lock();
     try {
       if (myReader == null) return null;
-      return myReader.getDirectInheritors(aClass,
-                                          searchElementInfo,
-                                          searchAdapter,
-                                          useScope,
-                                          myDirtyModulesHolder.getDirtyScope(),
-                                          myProject,
-                                          searchFileType);
+      return myReader.getDirectInheritors(aClass, searchElement, useScope, myDirtyModulesHolder.getDirtyScope(), myProject, searchFileType, searchType);
     } finally {
       myReadDataLock.unlock();
     }
   }
 
   @Nullable
-  private GlobalSearchScope calculateScopeWithoutReferences(@NotNull PsiElement element, CompilerSearchAdapter adapter) {
-    TIntHashSet referentFileIds = getReferentFileIds(element, adapter);
+  private GlobalSearchScope calculateScopeWithoutReferences(@NotNull PsiElement element) {
+    TIntHashSet referentFileIds = getReferentFileIds(element);
     if (referentFileIds == null) return null;
 
     return getScopeRestrictedByFileTypes(new ScopeWithoutReferencesOnCompilation(referentFileIds).intersectWith(notScope(myDirtyModulesHolder.getDirtyScope())),
@@ -283,45 +253,60 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
   }
 
   @Nullable
-  private TIntHashSet getReferentFileIds(@NotNull PsiElement element, @NotNull CompilerSearchAdapter adapter) {
-    final CompilerElementInfo compilerElementInfo = asCompilerElements(element, adapter, true);
+  private TIntHashSet getReferentFileIds(@NotNull PsiElement element) {
+    final CompilerElementInfo compilerElementInfo = asCompilerElements(element, true);
     if (compilerElementInfo == null) return null;
 
     myReadDataLock.lock();
     try {
       if (myReader == null) return null;
       TIntHashSet referentFileIds = new TIntHashSet();
-      for (CompilerElement compilerElement : compilerElementInfo.searchElements) {
-        final TIntHashSet referents = myReader.findReferentFileIds(compilerElement, adapter, compilerElementInfo.place == ElementPlace.SRC);
+      for (LightRef ref : compilerElementInfo.searchElements) {
+        final TIntHashSet referents = myReader.findReferentFileIds(ref, compilerElementInfo.place == ElementPlace.SRC);
         if (referents == null) return null;
         referentFileIds.addAll(referents.toArray());
       }
       return referentFileIds;
+
     } finally {
       myReadDataLock.unlock();
     }
   }
 
   @Nullable
-  private CompilerElementInfo asCompilerElements(@NotNull PsiElement psiElement, @NotNull CompilerSearchAdapter adapter, boolean buildHierarchyForLibraryElements) {
-    VirtualFile file = PsiUtilCore.getVirtualFile(psiElement);
-    ElementPlace place = ElementPlace.get(file, myProjectFileIndex);
-    if (place == null || (place == ElementPlace.SRC && myDirtyModulesHolder.contains(file))) {
-      return null;
+  private CompilerElementInfo asCompilerElements(@NotNull PsiElement psiElement, boolean buildHierarchyForLibraryElements) {
+    myReadDataLock.lock();
+    try {
+      if (myReader == null) return null;
+      VirtualFile file = PsiUtilCore.getVirtualFile(psiElement);
+      ElementPlace place = ElementPlace.get(file, myProjectFileIndex);
+      if (place == null || (place == ElementPlace.SRC && myDirtyModulesHolder.contains(file))) {
+        return null;
+      }
+      final LanguageLightRefAdapter<?, ?> adapter = findAdapterForFileType(file.getFileType());
+      final LightRef ref = ReadAction.compute(() -> adapter.asLightUsage(psiElement, myReader.getNameEnumerator()));
+      if (ref == null) return null;
+      if (place == ElementPlace.LIB && buildHierarchyForLibraryElements) {
+        final List<LightRef> elements = adapter.getHierarchyRestrictedToLibraryScope(ref,
+                                                                                     psiElement,
+                                                                                     myReader.getNameEnumerator(),
+                                                                                     LibraryScopeCache.getInstance(myProject).getLibrariesOnlyScope());
+        final LightRef[] fullHierarchy = new LightRef[elements.size() + 1];
+        fullHierarchy[0] = ref;
+        int i = 1;
+        for (LightRef element : elements) {
+          fullHierarchy[i++] = element;
+        }
+        return new CompilerElementInfo(place, fullHierarchy);
+      }
+      else {
+        return new CompilerElementInfo(place, ref);
+      }
+    } finally {
+      myReadDataLock.unlock();
     }
 
-    final CompilerElement compilerElement = ReadAction.compute(() -> adapter.asCompilerElement(psiElement));
-    if (compilerElement == null) return null;
-    if (place == ElementPlace.LIB && buildHierarchyForLibraryElements) {
-      final CompilerElement[] elements = adapter.getHierarchyRestrictedToLibrariesScope(compilerElement, psiElement);
-      final CompilerElement[] fullHierarchy = new CompilerElement[elements.length + 1];
-      fullHierarchy[0] = compilerElement;
-      System.arraycopy(elements, 0, fullHierarchy, 1, elements.length);
-      return new CompilerElementInfo(place, fullHierarchy);
-    }
-    else {
-      return new CompilerElementInfo(place, compilerElement);
-    }
+
   }
 
   private void closeReaderIfNeed() {
@@ -349,9 +334,9 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
 
   @TestOnly
   @Nullable
-  public Set<VirtualFile> getReferentFiles(@NotNull PsiElement element, @NotNull CompilerSearchAdapter adapter) {
+  public Set<VirtualFile> getReferentFiles(@NotNull PsiElement element) {
     FileBasedIndex fileIndex = FileBasedIndex.getInstance();
-    final TIntHashSet ids = getReferentFileIds(element, adapter);
+    final TIntHashSet ids = getReferentFileIds(element);
     if (ids == null) return null;
     Set<VirtualFile> fileSet = new THashSet<>();
     ids.forEach(id -> {
@@ -363,6 +348,35 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
     return fileSet;
   }
 
+  ProjectFileIndex getFileIndex() {
+    return myProjectFileIndex;
+  }
+
+  Set<FileType> getFileTypes() {
+    return myFileTypes;
+  }
+
+  Project getProject() {
+    return myProject;
+  }
+
+  static LanguageLightRefAdapter findAdapterForFileType(@NotNull FileType fileType) {
+    for (LanguageLightRefAdapter adapter : LanguageLightRefAdapter.INSTANCES) {
+      if (adapter.getFileTypes().contains(fileType)) {
+        return adapter;
+      }
+    }
+    throw new AssertionError("adapter is not found for: " + fileType);
+  }
+
+  private static void executeOnBuildThread(Runnable compilationFinished) {
+    if (ApplicationManager.getApplication().isUnitTestMode()) {
+      compilationFinished.run();
+    } else {
+      BuildManager.getInstance().runCommand(compilationFinished);
+    }
+  }
+
   private enum ElementPlace {
     SRC, LIB;
 
@@ -405,103 +419,37 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
     return myCompilationCount.longValue();
   }
 
-  private class DirtyModulesHolder extends UserDataHolderBase {
-    private final Set<Module> myChangedModules = ContainerUtil.newHashSet();
-    private final Set<Module> myChangedModulesDuringCompilation = ContainerUtil.newHashSet();
-    private boolean myCompilationPhase;
-
-    private final Object myLock = new Object();
-
-    private void compilerActivityStarted() {
-      synchronized (myLock) {
-        myCompilationPhase = true;
-      }
-    }
-
-    private void compilerActivityFinished(Module[] affectedModules, Module[] markAsDirty) {
-      synchronized (myLock) {
-        myCompilationPhase = false;
-
-        ContainerUtil.removeAll(myChangedModules, affectedModules);
-        Collections.addAll(myChangedModules, markAsDirty);
-        myChangedModules.addAll(myChangedModulesDuringCompilation);
-        myChangedModulesDuringCompilation.clear();
-      }
-    }
-
-    private GlobalSearchScope getDirtyScope() {
-      return CachedValuesManager.getManager(myProject).getCachedValue(this, () -> {
-        synchronized (myLock) {
-          final GlobalSearchScope dirtyScope =
-            myChangedModules.stream().map(Module::getModuleWithDependentsScope).reduce(EMPTY_SCOPE, (s1, s2) -> s1.union(s2));
-          return CachedValueProvider.Result.create(dirtyScope, PsiModificationTracker.MODIFICATION_COUNT, CompilerReferenceServiceImpl.this);
-        }
-      });
-    }
-
-    private void fileChanged(VirtualFile file) {
-      if (myProjectFileIndex.isInSourceContent(file) && myFileTypes.contains(file.getFileType())) {
-        final Module module = myProjectFileIndex.getModuleForFile(file);
-        if (module != null) {
-          synchronized (myLock) {
-            if (myCompilationPhase) {
-              myChangedModulesDuringCompilation.add(module);
-            } else {
-              myChangedModules.add(module);
-            }
-          }
-        }
-      }
-    }
-
-    private boolean contains(VirtualFile file) {
-      return getDirtyScope().contains(file);
-    }
-  }
-
   static class CompilerElementInfo {
     final ElementPlace place;
-    final CompilerElement[] searchElements;
+    final LightRef[] searchElements;
 
-    private CompilerElementInfo(ElementPlace place, CompilerElement... searchElements) {
-      this.searchElements = searchElements;
+    private CompilerElementInfo(ElementPlace place, LightRef... searchElements) {
       this.place = place;
+      this.searchElements = searchElements;
     }
   }
 
-  private static class CompilerDirectInheritorInfoImpl<T extends PsiNamedElement> implements CompilerDirectInheritorInfo<T> {
-    private final GlobalSearchScope myDirtyScope;
-    private final GlobalSearchScope mySearchScope;
-    private Couple<Map<VirtualFile, T[]>> myCandidatePerFile;
-
-    private CompilerDirectInheritorInfoImpl(Couple<Map<VirtualFile, T[]>> candidatePerFile,
-                                            GlobalSearchScope dirtyScope,
-                                            GlobalSearchScope searchScope) {
-      myCandidatePerFile = candidatePerFile;
-      myDirtyScope = dirtyScope;
-      mySearchScope = searchScope;
-    }
+  private static class HierarchySearchKey {
+    private final CompilerHierarchySearchType mySearchType;
+    private final FileType mySearchFileType;
 
-    @Override
-    @NotNull
-    public Stream<T> getDirectInheritors() {
-      return selectClassesInScope(myCandidatePerFile.getFirst(), mySearchScope);
+    HierarchySearchKey(CompilerHierarchySearchType searchType, FileType searchFileType) {
+      mySearchType = searchType;
+      mySearchFileType = searchFileType;
     }
 
     @Override
-    @NotNull
-    public Stream<T> getDirectInheritorCandidates() {
-      return selectClassesInScope(myCandidatePerFile.getSecond(), mySearchScope);
-    }
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
 
-    @Override
-    @NotNull
-    public GlobalSearchScope getDirtyScope() {
-      return myDirtyScope;
+      HierarchySearchKey key = (HierarchySearchKey)o;
+      return mySearchType == key.mySearchType && mySearchFileType == key.mySearchFileType;
     }
 
-    private static <T extends PsiNamedElement> Stream<T> selectClassesInScope(Map<VirtualFile, T[]> classesPerFile, GlobalSearchScope searchScope) {
-      return classesPerFile.entrySet().stream().filter(e -> searchScope.contains(e.getKey())).flatMap(e -> Stream.of(e.getValue()));
+    @Override
+    public int hashCode() {
+      return 31 * mySearchType.hashCode() + mySearchFileType.hashCode();
     }
   }
 }
diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/DirtyModulesHolder.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/DirtyModulesHolder.java
new file mode 100644 (file)
index 0000000..4f335db
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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.openapi.module.Module;
+import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.openapi.vfs.*;
+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.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.Set;
+
+import static com.intellij.psi.search.GlobalSearchScope.EMPTY_SCOPE;
+
+class DirtyModulesHolder extends UserDataHolderBase {
+  private final CompilerReferenceServiceImpl myService;
+  private final Set<Module> myChangedModules = ContainerUtil.newHashSet();
+  private final Set<Module> myChangedModulesDuringCompilation = ContainerUtil.newHashSet();
+  private final Object myLock = new Object();
+
+  private boolean myCompilationPhase;
+
+  public DirtyModulesHolder(@NotNull CompilerReferenceServiceImpl service){
+    myService = service;
+  }
+
+  void compilerActivityStarted() {
+    synchronized (myLock) {
+      myCompilationPhase = true;
+    }
+  }
+
+  void compilerActivityFinished(Module[] affectedModules, Module[] markAsDirty) {
+    synchronized (myLock) {
+      myCompilationPhase = false;
+
+      ContainerUtil.removeAll(myChangedModules, affectedModules);
+      Collections.addAll(myChangedModules, markAsDirty);
+      myChangedModules.addAll(myChangedModulesDuringCompilation);
+      myChangedModulesDuringCompilation.clear();
+    }
+  }
+
+  GlobalSearchScope getDirtyScope() {
+    return CachedValuesManager.getManager(myService.getProject()).getCachedValue(this, () -> {
+      synchronized (myLock) {
+        final GlobalSearchScope dirtyScope =
+          myChangedModules.stream().map(Module::getModuleWithDependentsScope).reduce(EMPTY_SCOPE, (s1, s2) -> s1.union(s2));
+        return CachedValueProvider.Result.create(dirtyScope, PsiModificationTracker.MODIFICATION_COUNT, myService);
+      }
+    });
+  }
+
+  boolean contains(VirtualFile file) {
+    return getDirtyScope().contains(file);
+  }
+
+  void installVFSListener() {
+    VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() {
+      @Override
+      public void fileCreated(@NotNull VirtualFileEvent event) {
+        processChange(event.getFile());
+      }
+
+      @Override
+      public void fileCopied(@NotNull VirtualFileCopyEvent event) {
+        processChange(event.getFile());
+      }
+
+      @Override
+      public void fileMoved(@NotNull VirtualFileMoveEvent event) {
+        processChange(event.getFile());
+      }
+
+      @Override
+      public void beforePropertyChange(@NotNull VirtualFilePropertyEvent event) {
+        if (VirtualFile.PROP_NAME.equals(event.getPropertyName()) || VirtualFile.PROP_SYMLINK_TARGET.equals(event.getPropertyName())) {
+          processChange(event.getFile());
+        }
+      }
+
+      @Override
+      public void beforeContentsChange(@NotNull VirtualFileEvent event) {
+        processChange(event.getFile());
+      }
+
+      @Override
+      public void beforeFileDeletion(@NotNull VirtualFileEvent event) {
+        processChange(event.getFile());
+      }
+
+      @Override
+      public void beforeFileMovement(@NotNull VirtualFileMoveEvent event) {
+        processChange(event.getFile());
+      }
+
+      private void processChange(VirtualFile file) {
+        fileChanged(file);
+      }
+
+      void fileChanged(VirtualFile file) {
+        if (myService.getFileIndex().isInSourceContent(file) && myService.getFileTypes().contains(file.getFileType())) {
+          final Module module = myService.getFileIndex().getModuleForFile(file);
+          if (module != null) {
+            synchronized (myLock) {
+              if (myCompilationPhase) {
+                myChangedModulesDuringCompilation.add(module);
+              } else {
+                myChangedModules.add(module);
+              }
+            }
+          }
+        }
+      }
+    }, myService.getProject());
+
+  }
+}
similarity index 52%
rename from java/java-indexing-impl/src/com/intellij/compiler/JavaBaseCompilerSearchAdapter.java
rename to java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaCompilerElementRetriever.java
index 06178cd9da1f02b3b809679f90b51a0054938397..a5216fe2f4943867844e6a6b64de6bad3d5a7535 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.compiler;
+package com.intellij.compiler.backwardRefs;
 
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.application.ReadAction;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.impl.LibraryScopeCache;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
+import com.intellij.psi.impl.java.stubs.FunctionalExpressionStub;
 import com.intellij.psi.impl.java.stubs.PsiClassStub;
-import com.intellij.psi.impl.java.stubs.impl.PsiClassStubImpl;
 import com.intellij.psi.impl.source.PsiFileImpl;
 import com.intellij.psi.impl.source.PsiFileWithStubSupport;
-import com.intellij.psi.search.searches.ClassInheritorsSearch;
+import com.intellij.psi.impl.source.tree.JavaElementType;
+import com.intellij.psi.stubs.StubBase;
 import com.intellij.psi.stubs.StubElement;
 import com.intellij.psi.stubs.StubTree;
-import com.intellij.psi.util.ClassUtil;
-import com.intellij.util.ObjectUtils;
-import com.intellij.util.Processor;
+import com.intellij.psi.tree.TokenSet;
+import gnu.trove.TIntHashSet;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
-public class JavaBaseCompilerSearchAdapter implements ClassResolvingCompilerSearchAdapter<PsiClass> {
-  public static final JavaBaseCompilerSearchAdapter INSTANCE = new JavaBaseCompilerSearchAdapter();
+public class JavaCompilerElementRetriever {
+  private final static TokenSet FUN_EXPR = TokenSet.create(JavaElementType.LAMBDA_EXPRESSION, JavaElementType.METHOD_REF_EXPRESSION);
 
-  @Override
-  public boolean needOverrideElement() {
-    return true;
-  }
+  @NotNull
+  static PsiFunctionalExpression[] retrieveFunExpressionsByIndices(@NotNull TIntHashSet indices,
+                                                                   @NotNull PsiFileWithStubSupport psiFile) {
+    StubTree tree = psiFile.getStubTree();
+    boolean foreign = tree == null;
+    if (foreign) {
+      tree = ((PsiFileImpl)psiFile).calcStubTree();
+    }
 
-  @Nullable
-  @Override
-  public CompilerElement asCompilerElement(@NotNull PsiElement element) {
-    if (mayBeVisibleOutsideOwnerFile(element)) {
-      if (element instanceof PsiField) {
-        final PsiField field = (PsiField)element;
-        final PsiClass aClass = field.getContainingClass();
-        if (aClass == null || aClass instanceof PsiAnonymousClass) return null;
-        final String jvmOwnerName = ClassUtil.getJVMClassName(aClass);
-        final String name = field.getName();
-        if (name == null || jvmOwnerName == null) return null;
-        return new CompilerElement.CompilerField(jvmOwnerName, name);
-      }
-      else if (element instanceof PsiMethod) {
-        final PsiClass aClass = ((PsiMethod)element).getContainingClass();
-        if (aClass == null || aClass instanceof PsiAnonymousClass) return null;
-        final String jvmOwnerName = ClassUtil.getJVMClassName(aClass);
-        if (jvmOwnerName == null) return null;
-        final PsiMethod method = (PsiMethod)element;
-        final String name = method.isConstructor() ? "<init>" : method.getName();
-        final int parametersCount = method.getParameterList().getParametersCount();
-        return new CompilerElement.CompilerMethod(jvmOwnerName, name, parametersCount);
-      }
-      else if (element instanceof PsiClass) {
-        final String jvmClassName = ClassUtil.getJVMClassName((PsiClass)element);
-        if (jvmClassName != null) {
-          return new CompilerElement.CompilerClass(jvmClassName);
-        }
+    PsiFunctionalExpression[] result = new PsiFunctionalExpression[indices.size()];
+    int resIdx = 0;
+    int funExprIdx = 0;
+    for (StubElement<?> element : tree.getPlainList()) {
+      if (FUN_EXPR.contains(element.getStubType()) && indices.contains(funExprIdx++)) {
+        result[resIdx++] = asPsi((FunctionalExpressionStub<?>) element, psiFile, tree, foreign);
       }
     }
-    return null;
-  }
-
-  @NotNull
-  @Override
-  public CompilerElement[] getHierarchyRestrictedToLibrariesScope(@NotNull CompilerElement baseLibraryElement, @NotNull PsiElement baseLibraryPsi) {
-    final PsiClass baseClass = ObjectUtils.notNull(baseLibraryPsi instanceof PsiClass ? (PsiClass)baseLibraryPsi : ((PsiMember)baseLibraryPsi).getContainingClass());
-    final List<CompilerElement> overridden = new ArrayList<>();
-    Processor<PsiClass> processor = c -> {
-      if (c.hasModifierProperty(PsiModifier.PRIVATE)) return true;
-      String qName = c.getQualifiedName();
-      if (qName == null) return true;
-      overridden.add(baseLibraryElement.override(qName));
-      return true;
-    };
-    ClassInheritorsSearch.search(baseClass, LibraryScopeCache.getInstance(baseClass.getProject()).getLibrariesOnlyScope(), true).forEach(processor);
-    return overridden.toArray(new CompilerElement[overridden.size()]);
+    return result;
   }
 
   @NotNull
-  @Override
-  public PsiClass[] getCandidatesFromFile(@NotNull Collection<String> classInternalNames,
-                                          @NotNull PsiNamedElement superClass,
-                                          @NotNull VirtualFile containingFile,
-                                          @NotNull Project project) {
-    Collection<InternalClassMatcher> matchers = createClassMatcher(classInternalNames, superClass);
-    return ReadAction.compute(() -> retrieveMatchedClasses(containingFile, project, matchers).toArray(PsiClass.EMPTY_ARRAY));
-  }
-
-  private static boolean mayBeVisibleOutsideOwnerFile(@NotNull PsiElement element) {
-    if (!(element instanceof PsiModifierListOwner)) return true;
-    if (((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.PRIVATE)) return false;
-    return true;
+  static PsiClass[] retrieveClassesByInternalNames(@NotNull String[] internalNames,
+                                                   @NotNull PsiNamedElement baseClass,
+                                                   @NotNull PsiFileWithStubSupport psiFile) {
+    Collection<InternalClassMatcher> matchers = createClassMatcher(internalNames, baseClass);
+    return ReadAction.compute(() -> retrieveMatchedClasses(psiFile, matchers).toArray(PsiClass.EMPTY_ARRAY));
   }
 
-  private static List<PsiClass> retrieveMatchedClasses(VirtualFile file, Project project, Collection<InternalClassMatcher> matchers) {
+  private static List<PsiClass> retrieveMatchedClasses(PsiFileWithStubSupport psiFile, Collection<InternalClassMatcher> matchers) {
     final List<PsiClass> result = new ArrayList<>(matchers.size());
-    PsiFileWithStubSupport psiFile = ObjectUtils.notNull((PsiFileWithStubSupport)PsiManager.getInstance(project).findFile(file));
     StubTree tree = psiFile.getStubTree();
     boolean foreign = tree == null;
     if (foreign) {
@@ -123,20 +76,21 @@ public class JavaBaseCompilerSearchAdapter implements ClassResolvingCompilerSear
 
     for (StubElement<?> element : tree.getPlainList()) {
       if (element instanceof PsiClassStub && match((PsiClassStub)element, matchers)) {
-        result.add(asPsi((PsiClassStub<?>)element, psiFile, tree, foreign));
+        result.add(asPsi((StubBase<PsiClass>)element, psiFile, tree, foreign));
       }
     }
 
     return result;
   }
 
-  private static PsiClass asPsi(PsiClassStub<?> stub, PsiFileWithStubSupport file, StubTree tree, boolean foreign) {
+
+  private static <T extends PsiElement> T asPsi(StubBase<T> stub, PsiFileWithStubSupport file, StubTree tree, boolean foreign) {
     if (foreign) {
-      final PsiClass cachedPsi = ((PsiClassStubImpl<?>)stub).getCachedPsi();
+      final T cachedPsi = (stub).getCachedPsi();
       if (cachedPsi != null) return cachedPsi;
 
       final ASTNode ast = file.findTreeForStub(tree, stub);
-      return ast != null ? (PsiClass)ast.getPsi() : null;
+      return ast != null ? (T)ast.getPsi() : null;
     }
     return stub.getPsi();
   }
@@ -154,9 +108,9 @@ public class JavaBaseCompilerSearchAdapter implements ClassResolvingCompilerSear
     return false;
   }
 
-  private static Collection<InternalClassMatcher> createClassMatcher(@NotNull Collection<String> internalNames, @NotNull PsiNamedElement baseClass) {
+  private static Collection<InternalClassMatcher> createClassMatcher(@NotNull String[] internalNames, @NotNull PsiNamedElement baseClass) {
     boolean matcherBySuperNameAdded = false;
-    final List<InternalClassMatcher> matchers = new ArrayList<>(internalNames.size());
+    final List<InternalClassMatcher> matchers = new ArrayList<>(internalNames.length);
     for (String internalName : internalNames) {
       int curLast = internalName.length() - 1;
       while (true) {
diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaLightUsageAdapter.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaLightUsageAdapter.java
new file mode 100644 (file)
index 0000000..63ccf50
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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.ide.highlighter.JavaClassFileType;
+import com.intellij.ide.highlighter.JavaFileType;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.roots.impl.LibraryScopeCache;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.PsiFileWithStubSupport;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.searches.ClassInheritorsSearch;
+import com.intellij.psi.util.ClassUtil;
+import com.intellij.util.ObjectUtils;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
+import com.sun.tools.javac.util.Convert;
+import gnu.trove.TIntHashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator;
+import org.jetbrains.jps.backwardRefs.LightRef;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+public class JavaLightUsageAdapter implements LanguageLightRefAdapter<PsiClass, PsiFunctionalExpression> {
+  @NotNull
+  @Override
+  public Set<FileType> getFileTypes() {
+    return ContainerUtil.set(JavaFileType.INSTANCE, JavaClassFileType.INSTANCE);
+  }
+
+  @Override
+  public LightRef asLightUsage(@NotNull PsiElement element, @NotNull ByteArrayEnumerator names) {
+    if (mayBeVisibleOutsideOwnerFile(element)) {
+      if (element instanceof PsiField) {
+        final PsiField field = (PsiField)element;
+        final PsiClass aClass = field.getContainingClass();
+        if (aClass == null || aClass instanceof PsiAnonymousClass) return null;
+        final String jvmOwnerName = ClassUtil.getJVMClassName(aClass);
+        final String name = field.getName();
+        if (name == null || jvmOwnerName == null) return null;
+        return new LightRef.JavaLightFieldRef(id(jvmOwnerName, names), id(name, names));
+      }
+      else if (element instanceof PsiMethod) {
+        final PsiClass aClass = ((PsiMethod)element).getContainingClass();
+        if (aClass == null || aClass instanceof PsiAnonymousClass) return null;
+        final String jvmOwnerName = ClassUtil.getJVMClassName(aClass);
+        if (jvmOwnerName == null) return null;
+        final PsiMethod method = (PsiMethod)element;
+        final String name = method.isConstructor() ? "<init>" : method.getName();
+        final int parametersCount = method.getParameterList().getParametersCount();
+        return new LightRef.JavaLightMethodRef(id(jvmOwnerName, names), id(name, names), parametersCount);
+      }
+      else if (element instanceof PsiClass) {
+        final String jvmClassName = ClassUtil.getJVMClassName((PsiClass)element);
+        if (jvmClassName != null) {
+          return new LightRef.JavaLightClassRef(id(jvmClassName, names));
+        }
+      }
+    }
+    return null;
+  }
+
+  @NotNull
+  @Override
+  public List<LightRef> getHierarchyRestrictedToLibraryScope(@NotNull LightRef baseRef,
+                                                             @NotNull PsiElement basePsi,
+                                                             @NotNull ByteArrayEnumerator names, @NotNull GlobalSearchScope libraryScope) {
+    final PsiClass baseClass = ObjectUtils.notNull(basePsi instanceof PsiClass ? (PsiClass)basePsi : ((PsiMember)basePsi).getContainingClass());
+
+    final List<LightRef> overridden = new ArrayList<>();
+    Processor<PsiClass> processor = c -> {
+      if (c.hasModifierProperty(PsiModifier.PRIVATE)) return true;
+      String qName = c.getQualifiedName();
+      if (qName == null) return true;
+      overridden.add(baseRef.override(id(qName, names)));
+      return true;
+    };
+
+    ClassInheritorsSearch.search(baseClass, LibraryScopeCache.getInstance(baseClass.getProject()).getLibrariesOnlyScope(), true).forEach(processor);
+    return overridden;
+
+  }
+
+  @NotNull
+  @Override
+  public Class<? extends LightRef.LightClassHierarchyElementDef> getHierarchyObjectClass() {
+    return LightRef.JavaLightClassRef.class;
+  }
+
+  @NotNull
+  @Override
+  public Class<? extends LightRef> getFunExprClass() {
+    return LightRef.JavaLightFunExprDef.class;
+  }
+
+  @NotNull
+  @Override
+  public PsiClass[] findDirectInheritorCandidatesInFile(@NotNull Collection<LightRef.LightClassHierarchyElementDef> classes,
+                                                        @NotNull ByteArrayEnumerator byteArrayEnumerator,
+                                                        @NotNull PsiFileWithStubSupport file,
+                                                        @NotNull PsiNamedElement superClass) {
+    String[] internalNames = classes.stream().map(LightRef.NamedLightRef::getName).map(byteArrayEnumerator::getName).toArray(String[]::new);
+    return JavaCompilerElementRetriever.retrieveClassesByInternalNames(internalNames, superClass, file);
+  }
+
+  @NotNull
+  @Override
+  public PsiFunctionalExpression[] findFunExpressionsInFile(@NotNull Collection<LightRef.LightFunExprDef> funExpressions,
+                                                            @NotNull PsiFileWithStubSupport file) {
+    TIntHashSet requiredIndices = new TIntHashSet(funExpressions.size());
+    for (LightRef.LightFunExprDef funExpr : funExpressions) {
+      requiredIndices.add(funExpr.getId());
+    }
+    return JavaCompilerElementRetriever.retrieveFunExpressionsByIndices(requiredIndices, file);
+  }
+
+  private static boolean mayBeVisibleOutsideOwnerFile(@NotNull PsiElement element) {
+    if (!(element instanceof PsiModifierListOwner)) return true;
+    if (((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.PRIVATE)) return false;
+    return true;
+  }
+
+  private static int id(String name, ByteArrayEnumerator names) {
+    return names.enumerate(Convert.string2utf(name));
+  }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/LanguageLightRefAdapter.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/LanguageLightRefAdapter.java
new file mode 100644 (file)
index 0000000..e7705ef
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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.openapi.fileTypes.FileType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.impl.source.PsiFileWithStubSupport;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator;
+import org.jetbrains.jps.backwardRefs.LightRef;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * An interface to provide connection between compact internal representation of indexed elements and PSI
+ */
+public interface LanguageLightRefAdapter<Clazz extends PsiElement, FunExpr extends PsiElement> {
+  LanguageLightRefAdapter<?, ?>[] INSTANCES = new LanguageLightRefAdapter[]{new JavaLightUsageAdapter()};
+
+  @NotNull
+  Set<FileType> getFileTypes();
+
+  /**
+   * @param element PSI element written in corresponding language
+   * @param names enumerator to encode string names
+   * @return
+   */
+  @Nullable
+  LightRef asLightUsage(@NotNull PsiElement element, @NotNull ByteArrayEnumerator names);
+
+  /**
+   * @return "hierarchy" of given element inside the libraries scope.
+   */
+  @NotNull
+  List<LightRef> getHierarchyRestrictedToLibraryScope(@NotNull LightRef baseRef,
+                                                      @NotNull PsiElement basePsi,
+                                                      @NotNull ByteArrayEnumerator names,
+                                                      @NotNull GlobalSearchScope libraryScope);
+
+  /**
+   * class in java, class or object in some other jvm languages. used in direct inheritor search. This class object will be used to filter
+   * inheritors of corresponding language among of other inheritors.
+   *
+   * name of this LightUsage is always enumerated internal string name of language object, eg.: A$1$B
+   */
+  @NotNull
+  Class<? extends LightRef.LightClassHierarchyElementDef> getHierarchyObjectClass();
+
+  /**
+   * functional expression: lambda or method reference. used in functional expression search
+   *
+   * name of this LightUsage is always order-index inside source-code file
+   */
+  @NotNull
+  Class<? extends LightRef> getFunExprClass();
+
+  /**
+   * @return classes that can be inheritors of given superClass. This method shouldn't directly check are
+   * found elements really inheritors.
+   */
+  @NotNull
+  Clazz[] findDirectInheritorCandidatesInFile(@NotNull Collection<LightRef.LightClassHierarchyElementDef> internalNames,
+                                              @NotNull ByteArrayEnumerator byteArrayEnumerator,
+                                              @NotNull PsiFileWithStubSupport file,
+                                              @NotNull PsiNamedElement superClass);
+
+  /**
+   * @param indices - ordinal-numbers (corresponding to compiler tree index visitor) of required functional expressions.
+   * @return functional expressions for given functional type. Should return
+   */
+  @NotNull
+  FunExpr[] findFunExpressionsInFile(@NotNull Collection<LightRef.LightFunExprDef> indices,
+                                     @NotNull PsiFileWithStubSupport file);
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/LanguageLightUsageConverter.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/LanguageLightUsageConverter.java
deleted file mode 100644 (file)
index 4377148..0000000
+++ /dev/null
@@ -1,82 +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 com.intellij.compiler.backwardRefs;
-
-import com.intellij.compiler.CompilerElement;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.StdFileTypes;
-import com.intellij.util.containers.ContainerUtil;
-import com.sun.tools.javac.util.Convert;
-import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator;
-import org.jetbrains.jps.backwardRefs.LightUsage;
-
-import java.util.Set;
-
-public interface LanguageLightUsageConverter {
-  LanguageLightUsageConverter[] INSTANCES = new LanguageLightUsageConverter[]{new Java()};
-
-  LightUsage asLightUsage(CompilerElement element, ByteArrayEnumerator names);
-
-  FileType getFileSourceType();
-
-  Set<Class<? extends LightUsage>> getLanguageLightUsageClasses();
-
-  class Java implements LanguageLightUsageConverter {
-    private static final Set<Class<? extends LightUsage>> JAVA_LIGHT_USAGE_CLASSES =
-      ContainerUtil.set(LightUsage.LightClassUsage.class, LightUsage.LightMethodUsage.class, LightUsage.LightFieldUsage.class);
-
-    @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;
-    }
-
-    @Override
-    public FileType getFileSourceType() {
-      return StdFileTypes.JAVA;
-    }
-
-    @Override
-    public Set<Class<? extends LightUsage>> getLanguageLightUsageClasses() {
-      return JAVA_LIGHT_USAGE_CLASSES;
-    }
-
-    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/ClassResolvingCompilerSearchAdapter.java b/java/java-indexing-impl/src/com/intellij/compiler/ClassResolvingCompilerSearchAdapter.java
deleted file mode 100644 (file)
index 3ddd559..0000000
+++ /dev/null
@@ -1,35 +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 com.intellij.compiler;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiNamedElement;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collection;
-
-public interface ClassResolvingCompilerSearchAdapter<T extends PsiNamedElement> extends CompilerSearchAdapter {
-
-  /**
-   * @param classInternalNames - collection compiler internal name of classes (e.g. org.some.Main$1 for java anonymous class)
-   */
-  @NotNull
-  T[] getCandidatesFromFile(@NotNull Collection<String> classInternalNames,
-                            @NotNull PsiNamedElement superClass,
-                            @NotNull VirtualFile containingFile,
-                            @NotNull Project project);
-}
similarity index 50%
rename from java/java-indexing-impl/src/com/intellij/compiler/CompilerSearchAdapter.java
rename to java/java-indexing-impl/src/com/intellij/compiler/CompilerDirectHierarchyInfo.java
index 12919b0d476e661949b46aba2bcec615fe1aa80e..5f4ba5ea132cff3ecb47d90ea0a3ced8ed42dab6 100644 (file)
 package com.intellij.compiler;
 
 import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.GlobalSearchScope;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
-public interface CompilerSearchAdapter {
+import java.util.stream.Stream;
 
-  boolean needOverrideElement();
+/**
+ * represents search result for functional expressions or inheritance hierarchy of given interface/class
+ */
+public interface CompilerDirectHierarchyInfo<T extends PsiElement> {
+  /**
+   * Can be used as direct hierarchy children without explicit inheritance verification
+   */
+  @NotNull
+  Stream<T> getHierarchyChildren();
 
-  @Nullable
-  CompilerElement asCompilerElement(@NotNull PsiElement psi);
+  /**
+   * Must be explicitly checked do they are really direct children in hierarchy of classes or functional expressions
+   */
+  @NotNull
+  Stream<T> getHierarchyChildCandidates();
 
+  /**
+   * A scope where compiler based index search was not performed
+   */
   @NotNull
-  CompilerElement[] getHierarchyRestrictedToLibrariesScope(@NotNull CompilerElement baseLibraryElement, @NotNull PsiElement baseLibraryPsi);
+  GlobalSearchScope getDirtyScope();
 }
diff --git a/java/java-indexing-impl/src/com/intellij/compiler/CompilerElement.java b/java/java-indexing-impl/src/com/intellij/compiler/CompilerElement.java
deleted file mode 100644 (file)
index b9a70c6..0000000
+++ /dev/null
@@ -1,108 +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 com.intellij.compiler;
-
-public abstract class CompilerElement {
-  public static final CompilerElement[] EMPTY_ARRAY = new CompilerElement[0];
-
-  public abstract CompilerElement override(String overriderName);
-
-  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;
-    }
-
-    @Override
-    public CompilerElement override(String overriderName) {
-      return new CompilerMethod(overriderName, myJavacMethodName, myJavacParameterCount);
-    }
-  }
-
-  public static class CompilerClass extends CompilerElement {
-    private final String myJavacName;
-
-    CompilerClass(String javacName) {
-      myJavacName = javacName;
-    }
-
-    public String getJavacName() {
-      return myJavacName;
-    }
-
-    @Override
-    public CompilerElement override(String overriderName) {
-      return new CompilerClass(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;
-    }
-
-    @Override
-    public CompilerElement override(String overriderName) {
-      return new CompilerField(overriderName, myJavacName);
-    }
-  }
-
-  public static class CompilerFunExpr extends CompilerElement {
-    private final String myJavacClassName;
-
-    CompilerFunExpr(String javacClassName) {
-      myJavacClassName = javacClassName;
-    }
-
-    public String getJavacClassName() {
-      return myJavacClassName;
-    }
-
-    @Override
-    public CompilerElement override(String overriderName) {
-      throw new UnsupportedOperationException();
-    }
-  }
-}
index 233ee14fb38326dc23e778df596991bb55190f2b..c42884c332a57c8c86f49e8bcc6230caae8464e4 100644 (file)
@@ -26,8 +26,6 @@ import com.intellij.psi.search.GlobalSearchScope;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.stream.Stream;
-
 public abstract class CompilerReferenceService extends AbstractProjectComponent {
   public static final RegistryValue IS_ENABLED_KEY = Registry.get("bytecode.ref.index");
 
@@ -40,37 +38,21 @@ public abstract class CompilerReferenceService extends AbstractProjectComponent
   }
 
   @Nullable
-  public abstract GlobalSearchScope getScopeWithoutCodeReferences(@NotNull PsiElement element, @NotNull CompilerSearchAdapter adapter);
+  public abstract GlobalSearchScope getScopeWithoutCodeReferences(@NotNull PsiElement element);
 
   @Nullable
-  public abstract <T extends PsiNamedElement> CompilerDirectInheritorInfo<T> getDirectInheritors(@NotNull PsiNamedElement aClass,
-                                                                                                 @NotNull GlobalSearchScope useScope,
-                                                                                                 @NotNull GlobalSearchScope searchScope,
-                                                                                                 @NotNull ClassResolvingCompilerSearchAdapter<T> inheritorSearchAdapter,
-                                                                                                 @NotNull FileType searchFileType);
+  public abstract <T extends PsiElement> CompilerDirectHierarchyInfo<T> getDirectInheritors(@NotNull PsiNamedElement aClass,
+                                                                                            @NotNull GlobalSearchScope useScope,
+                                                                                            @NotNull GlobalSearchScope searchScope,
+                                                                                            @NotNull FileType searchFileType);
 
+  @Nullable
+  public abstract <T extends PsiElement> CompilerDirectHierarchyInfo<T> getFunExpressions(@NotNull PsiNamedElement functionalInterface,
+                                                                                          @NotNull GlobalSearchScope useScope,
+                                                                                          @NotNull GlobalSearchScope searchScope,
+                                                                                          @NotNull FileType searchFileType);
 
   public static boolean isEnabled() {
     return IS_ENABLED_KEY.asBoolean();
   }
-
-  public interface CompilerDirectInheritorInfo<T extends PsiNamedElement> {
-    /**
-     * Can be used as direct inheritors without explicit inheritance verification
-     */
-    @NotNull
-    Stream<T> getDirectInheritors();
-
-    /**
-     * Must be explicitly checked do they are really direct inheritors
-     */
-    @NotNull
-    Stream<T> getDirectInheritorCandidates();
-
-    /**
-     * A scope where compiler based index search was not performed
-     */
-    @NotNull
-    GlobalSearchScope getDirtyScope();
-  }
 }
index bae091e37c1902d1968a3a08590d3a642c69d5eb..06dd10d82cc7a66d2dd25ace3cf1d6694182bbd4 100644 (file)
@@ -25,6 +25,6 @@ public class JavaCompilerReferencesCodeUsageScopeOptimizer implements ScopeOptim
   @Nullable
   @Override
   public GlobalSearchScope getScopeToExclude(@NotNull PsiElement element) {
-    return CompilerReferenceService.getInstance(element.getProject()).getScopeWithoutCodeReferences(element, JavaBaseCompilerSearchAdapter.INSTANCE);
+    return CompilerReferenceService.getInstance(element.getProject()).getScopeWithoutCodeReferences(element);
   }
 }
diff --git a/java/java-indexing-impl/src/com/intellij/compiler/JavaFunctionalExpressionCompilerSearchAdapter.java b/java/java-indexing-impl/src/com/intellij/compiler/JavaFunctionalExpressionCompilerSearchAdapter.java
deleted file mode 100644 (file)
index 2b33362..0000000
+++ /dev/null
@@ -1,45 +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 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[] getHierarchyRestrictedToLibrariesScope(@NotNull CompilerElement baseLibraryElement, @NotNull PsiElement baseLibraryPsi) {
-    return CompilerElement.EMPTY_ARRAY;
-  }
-}
index 8e4ad355ada7b5bde38c614e2c47d805f4a36362..e267486b576dfbbfbfdc7cb576550c59ea2fbb3f 100644 (file)
@@ -15,8 +15,8 @@
  */
 package com.intellij.psi.impl.search;
 
+import com.intellij.compiler.CompilerDirectHierarchyInfo;
 import com.intellij.compiler.CompilerReferenceService;
-import com.intellij.compiler.JavaBaseCompilerSearchAdapter;
 import com.intellij.concurrency.JobLauncher;
 import com.intellij.ide.highlighter.JavaFileType;
 import com.intellij.openapi.application.ApplicationManager;
@@ -76,10 +76,10 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
 
     SearchScope scope = parameters.getScope();
 
-    CompilerReferenceService.CompilerDirectInheritorInfo<PsiClass> info = performSearchUsingCompilerIndices(parameters, scope, project);
+    CompilerDirectHierarchyInfo<PsiClass> info = performSearchUsingCompilerIndices(parameters, scope, project);
     if (info != null) {
-      if (!processInheritorCandidates(info.getDirectInheritors(), consumer, parameters.includeAnonymous(), false, baseClass)) return false;
-      if (!processInheritorCandidates(info.getDirectInheritorCandidates(), consumer, parameters.includeAnonymous(), true, baseClass)) return false;
+      if (!processInheritorCandidates(info.getHierarchyChildren(), consumer, parameters.includeAnonymous(), false, baseClass)) return false;
+      if (!processInheritorCandidates(info.getHierarchyChildCandidates(), consumer, parameters.includeAnonymous(), true, baseClass)) return false;
       scope = scope.intersectWith(info.getDirtyScope());
       useScope = useScope.intersectWith(info.getDirtyScope());
     }
@@ -274,9 +274,9 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
     return ApplicationManager.getApplication().runReadAction((Computable<VirtualFile>)() -> PsiUtil.getJarFile(aClass));
   }
 
-  private static CompilerReferenceService.CompilerDirectInheritorInfo<PsiClass> performSearchUsingCompilerIndices(@NotNull DirectClassInheritorsSearch.SearchParameters parameters,
-                                                                                                                  @NotNull SearchScope useScope,
-                                                                                                                  @NotNull Project project) {
+  private static CompilerDirectHierarchyInfo<PsiClass> performSearchUsingCompilerIndices(@NotNull DirectClassInheritorsSearch.SearchParameters parameters,
+                                                                                         @NotNull SearchScope useScope,
+                                                                                         @NotNull Project project) {
     if (!(useScope instanceof GlobalSearchScope)) return null;
     SearchScope scope = parameters.getScope();
     if (!(scope instanceof GlobalSearchScope)) return null;
@@ -286,7 +286,6 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
     return compilerReferenceService.getDirectInheritors(searchClass,
                                                         (GlobalSearchScope)useScope,
                                                         (GlobalSearchScope)scope,
-                                                        JavaBaseCompilerSearchAdapter.INSTANCE,
                                                         JavaFileType.INSTANCE);
   }
 
index bd85cff86b929f860d572b3e589a431e8335456e..e401087d5a86c57d55ea20ac016870eb8506992e 100644 (file)
@@ -16,7 +16,8 @@
 package com.intellij.psi.impl.search;
 
 import com.intellij.compiler.CompilerReferenceService;
-import com.intellij.compiler.JavaFunctionalExpressionCompilerSearchAdapter;
+import com.intellij.compiler.CompilerDirectHierarchyInfo;
+import com.intellij.ide.highlighter.JavaFileType;
 import com.intellij.lang.injection.InjectedLanguageManager;
 import com.intellij.openapi.application.QueryExecutorBase;
 import com.intellij.openapi.application.ReadAction;
@@ -41,6 +42,7 @@ import com.intellij.psi.stubs.StubIndex;
 import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.util.PairProcessor;
 import com.intellij.util.Processor;
 import com.intellij.util.Processors;
@@ -50,6 +52,7 @@ import com.intellij.util.containers.JBIterable;
 import com.intellij.util.containers.MultiMap;
 import com.intellij.util.indexing.FileBasedIndex;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 
 import java.util.*;
@@ -64,6 +67,17 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
   @Override
   public void processQuery(@NotNull SearchParameters p, @NotNull Processor<PsiFunctionalExpression> consumer) {
     List<SamDescriptor> descriptors = calcDescriptors(p);
+    Project project = PsiUtilCore.getProjectInReadAction(p.getElementToSearch());
+    if (project == null) return;
+
+    SearchScope searchScope = ReadAction.compute(() -> p.getEffectiveSearchScope());
+    if (searchScope instanceof GlobalSearchScope && !performSearchUsingCompilerIndices(descriptors,
+                                                                                       (GlobalSearchScope)searchScope,
+                                                                                       project,
+                                                                                       consumer)) {
+      return;
+    }
+
     AtomicInteger exprCount = new AtomicInteger();
     AtomicInteger fileCount = new AtomicInteger();
 
@@ -112,13 +126,6 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
           if (samType == null) continue;
 
           SearchScope scope = samClass.getUseScope().intersectWith(queryParameters.getEffectiveSearchScope());
-
-          final GlobalSearchScope excludedScope =
-            CompilerReferenceService.getInstance(project).getScopeWithoutCodeReferences(samClass, JavaFunctionalExpressionCompilerSearchAdapter.INSTANCE);
-          if (excludedScope != null) {
-            scope = scope.intersectWith(GlobalSearchScope.notScope(excludedScope));
-          }
-
           descriptors.add(new SamDescriptor(samClass, saMethod, samType, GlobalSearchScopeUtil.toGlobalSearchScope(scope, project)));
         }
       }
@@ -141,7 +148,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
             ProgressManager.checkCanceled();
             result.putValues(file, infos);
             return true;
-          }, new JavaSourceFilterScope(descriptor.useScope));
+          }, new JavaSourceFilterScope(descriptor.effectiveUseScope));
         }
       });
     }
@@ -266,14 +273,14 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
 
   private static class SamDescriptor {
     final PsiClass samClass;
-    final GlobalSearchScope useScope;
     final int samParamCount;
     final boolean booleanCompatible;
     final boolean isVoid;
+    GlobalSearchScope effectiveUseScope;
 
     SamDescriptor(PsiClass samClass, PsiMethod samMethod, PsiType samType, GlobalSearchScope useScope) {
       this.samClass = samClass;
-      this.useScope = useScope;
+      this.effectiveUseScope = useScope;
       this.samParamCount = samMethod.getParameterList().getParametersCount();
       this.booleanCompatible = FunctionalExpressionKey.isBooleanCompatible(samType);
       this.isVoid = PsiType.VOID.equals(samType);
@@ -310,7 +317,7 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
 
         Set<String> likelyNames = ContainerUtil.newLinkedHashSet(className);
         StubIndex.getInstance().processElements(JavaMethodParameterTypesIndex.getInstance().getKey(), className,
-                                                project, useScope, PsiMethod.class, method -> {
+                                                project, effectiveUseScope, PsiMethod.class, method -> {
             ProgressManager.checkCanceled();
             likelyNames.add(method.getName());
             return true;
@@ -319,12 +326,50 @@ public class JavaFunctionalExpressionSearcher extends QueryExecutorBase<PsiFunct
         PsiSearchHelperImpl helper = (PsiSearchHelperImpl)PsiSearchHelper.SERVICE.getInstance(project);
         Processor<VirtualFile> processor = Processors.cancelableCollectProcessor(files);
         for (String word : likelyNames) {
-          helper.processFilesWithText(useScope, UsageSearchContext.IN_CODE, true, word, processor);
+          helper.processFilesWithText(effectiveUseScope, UsageSearchContext.IN_CODE, true, word, processor);
         }
       });
       return files;
     }
+  }
+
+  private static boolean performSearchUsingCompilerIndices(@NotNull List<SamDescriptor> descriptors,
+                                                           @NotNull GlobalSearchScope searchScope,
+                                                           @NotNull Project project,
+                                                           @NotNull Processor<PsiFunctionalExpression> consumer) {
+    CompilerReferenceService compilerReferenceService = CompilerReferenceService.getInstance(project);
+    for (SamDescriptor descriptor : descriptors) {
+      if (!processFunctionalExpressions(performSearchUsingCompilerIndices(descriptor,
+                                                                          searchScope,
+                                                                          compilerReferenceService), descriptor, consumer)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  private static CompilerDirectHierarchyInfo<PsiFunctionalExpression> performSearchUsingCompilerIndices(@NotNull SamDescriptor descriptor,
+                                                                                                        @NotNull GlobalSearchScope searchScope,
+                                                                                                        @NotNull CompilerReferenceService service) {
+    return service.getFunExpressions(descriptor.samClass, descriptor.effectiveUseScope, searchScope, JavaFileType.INSTANCE);
+  }
+
 
+  private static boolean processFunctionalExpressions(@Nullable CompilerDirectHierarchyInfo<PsiFunctionalExpression> funExprInfo,
+                                                      @NotNull SamDescriptor descriptor,
+                                                      @NotNull Processor<PsiFunctionalExpression> consumer) {
+    if (funExprInfo != null) {
+      Iterator<PsiFunctionalExpression> it = funExprInfo.getHierarchyChildren().iterator();
+      while (it.hasNext()) {
+        PsiFunctionalExpression next = it.next();
+        if (!consumer.process(next)) {
+          return false;
+        }
+      }
+      GlobalSearchScope dirtyScope = funExprInfo.getDirtyScope();
+      descriptor.effectiveUseScope = descriptor.effectiveUseScope.intersectWith(dirtyScope);
+    }
+    return true;
   }
 
 }
\ No newline at end of file
diff --git a/java/java-tests/testData/compiler/bytecodeReferences/testInnerFunExpressions/Foo.java b/java/java-tests/testData/compiler/bytecodeReferences/testInnerFunExpressions/Foo.java
new file mode 100644 (file)
index 0000000..df8ad24
--- /dev/null
@@ -0,0 +1,42 @@
+import java.util.function.IntSupplier;
+import java.util.Collections;
+
+class Foo {
+
+  void m() {
+
+    Runnable r = Collections::emptyList;
+
+    Runnable r2 = () -> {
+
+
+      IntSupplier s = () -> 1;
+
+      Runnable r3 = () -> {
+
+      };
+
+    };
+
+    IntSupplier s2 = () -> 1;
+  }
+
+  void m2() {
+
+    Runnable r = () -> {
+
+      Runnable r3 = () -> {
+
+        IntSupplier s2 = () -> 1;
+
+        Runnable r4 = () -> {
+
+        };
+
+      };
+
+      IntSupplier s = () -> 1;
+
+    };
+  }
+}
\ No newline at end of file
index e7d5c8a95c1eb0c791b0ef85982411708cb81747..d72162694c9ca874da082157b2c4231ddb22d1d8 100644 (file)
@@ -24,11 +24,14 @@ import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
 import com.intellij.testFramework.SkipSlowTestLocally;
 import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
 import com.intellij.util.containers.ContainerUtil;
 
 import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -55,37 +58,56 @@ public class CompilerReferencesTest extends AbstractCompilerAwareTest {
 
   public void testIsNotReady() {
     myFixture.configureByFile(getName() + "/Foo.java");
-    assertNull(getReferentFilesForElementUnderCaret(JavaBaseCompilerSearchAdapter.INSTANCE));
+    assertNull(getReferentFilesForElementUnderCaret());
   }
 
   public void testSimpleUsagesInFullyCompiledProject() {
     myFixture.configureByFiles(getName() + "/Foo.java", getName() + "/Bar.java", getName() + "/Baz.java", getName() + "/FooImpl.java");
     rebuildProject();
 
-    final Set<VirtualFile> referents = getReferentFilesForElementUnderCaret(JavaBaseCompilerSearchAdapter.INSTANCE);
+    final Set<VirtualFile> referents = getReferentFilesForElementUnderCaret();
     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(JavaBaseCompilerSearchAdapter.INSTANCE));
+    assertNull(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"));
+    final CompilerDirectHierarchyInfo<PsiFunctionalExpression> funExpressions = getFunctionalExpressionsForElementUnderCaret();
+    List<PsiFunctionalExpression> funExprs = funExpressions.getHierarchyChildren().collect(Collectors.toList());
+    assertSize(2, funExprs);
+  }
+
+  public void testInnerFunExpressions() {
+    myFixture.configureByFiles(getName() + "/Foo.java");
+    rebuildProject();
+    List<PsiFunctionalExpression> funExpressions =
+      getFunExpressionsFor(myFixture.getJavaFacade().findClass(CommonClassNames.JAVA_LANG_RUNNABLE)).getHierarchyChildren().collect(Collectors.toList());
+    assertSize(6, funExpressions);
+
+    Set<String> funTypeNames = funExpressions
+      .stream()
+      .map(PsiElement::getParent)
+      .map(PsiVariable.class::cast)
+      .map(PsiVariable::getType)
+      .map(PsiUtil::resolveClassInType)
+      .filter(Objects::nonNull)
+      .map(PsiClass::getQualifiedName)
+      .collect(Collectors.toSet());
+    String funTypeName = assertOneElement(funTypeNames);
+    assertEquals(CommonClassNames.JAVA_LANG_RUNNABLE, funTypeName);
   }
 
   public void testHierarchy() {
     myFixture.configureByFiles(getName() + "/Foo.java", getName() + "/FooImpl.java", getName() + "/Bar.java", getName() + "/Baz.java", getName() + "/Test.java");
     rebuildProject();
-    CompilerReferenceService.CompilerDirectInheritorInfo<PsiClass> directInheritorInfo = getHierarchyUnderForElementCaret();
+    CompilerDirectHierarchyInfo<PsiClass> directInheritorInfo = getHierarchyForElementUnderCaret();
 
-    Collection<PsiClass> inheritors = directInheritorInfo.getDirectInheritors().collect(Collectors.toList());
+    Collection<PsiClass> inheritors = directInheritorInfo.getHierarchyChildren().collect(Collectors.toList());
     assertSize(6, inheritors);
     for (PsiClass inheritor : inheritors) {
       if (inheritor instanceof PsiAnonymousClass) {
@@ -95,40 +117,54 @@ public class CompilerReferencesTest extends AbstractCompilerAwareTest {
       }
     }
 
-    Collection<PsiClass> candidates = directInheritorInfo.getDirectInheritorCandidates().collect(Collectors.toList());
+    Collection<PsiClass> candidates = directInheritorInfo.getHierarchyChildCandidates().collect(Collectors.toList());
     assertEmpty(candidates);
   }
 
   public void testHierarchyOfLibClass() {
     myFixture.configureByFiles(getName() + "/Foo.java");
     rebuildProject();
-    CompilerReferenceService.CompilerDirectInheritorInfo<PsiClass> directInheritorInfo = getHierarchyFor(myFixture.getJavaFacade().findClass(CommonClassNames.JAVA_UTIL_LIST));
-    PsiClass inheritor = assertOneElement(directInheritorInfo.getDirectInheritors().collect(Collectors.toList()));
+    CompilerDirectHierarchyInfo<PsiClass> directInheritorInfo = getDirectInheritorsFor(myFixture.getJavaFacade().findClass(CommonClassNames.JAVA_UTIL_LIST));
+    PsiClass inheritor = assertOneElement(directInheritorInfo.getHierarchyChildren().collect(Collectors.toList()));
     assertEquals("Foo.ListImpl", inheritor.getQualifiedName());
   }
 
-  private CompilerReferenceService.CompilerDirectInheritorInfo<PsiClass> getHierarchyUnderForElementCaret() {
+  private CompilerDirectHierarchyInfo<PsiClass> getHierarchyForElementUnderCaret() {
+    final PsiElement atCaret = myFixture.getElementAtCaret();
+    assertNotNull(atCaret);
+    final PsiClass classAtCaret = PsiTreeUtil.getParentOfType(atCaret, PsiClass.class, false);
+    assertNotNull(classAtCaret);
+    return getDirectInheritorsFor(classAtCaret);
+  }
+
+  private CompilerDirectHierarchyInfo<PsiFunctionalExpression> getFunctionalExpressionsForElementUnderCaret() {
     final PsiElement atCaret = myFixture.getElementAtCaret();
     assertNotNull(atCaret);
     final PsiClass classAtCaret = PsiTreeUtil.getParentOfType(atCaret, PsiClass.class, false);
     assertNotNull(classAtCaret);
-    return getHierarchyFor(classAtCaret);
+    return getFunExpressionsFor(classAtCaret);
   }
 
-  private CompilerReferenceService.CompilerDirectInheritorInfo<PsiClass> getHierarchyFor(PsiClass classAtCaret) {
+  private CompilerDirectHierarchyInfo<PsiClass> getDirectInheritorsFor(PsiClass classAtCaret) {
     return CompilerReferenceService.getInstance(myFixture.getProject()).getDirectInheritors(classAtCaret,
                                                                                             assertInstanceOf(classAtCaret.getUseScope(), GlobalSearchScope.class),
                                                                                             assertInstanceOf(classAtCaret.getUseScope(), GlobalSearchScope.class),
-                                                                                            JavaBaseCompilerSearchAdapter.INSTANCE,
                                                                                             StdFileTypes.JAVA);
   }
 
-  private Set<VirtualFile> getReferentFilesForElementUnderCaret(CompilerSearchAdapter adapter) {
+  private CompilerDirectHierarchyInfo<PsiFunctionalExpression> getFunExpressionsFor(PsiClass classAtCaret) {
+    return CompilerReferenceService.getInstance(myFixture.getProject()).getFunExpressions(classAtCaret,
+                                                                                          assertInstanceOf(classAtCaret.getUseScope(), GlobalSearchScope.class),
+                                                                                          assertInstanceOf(classAtCaret.getUseScope(), GlobalSearchScope.class),
+                                                                                          StdFileTypes.JAVA);
+  }
+
+  private Set<VirtualFile> getReferentFilesForElementUnderCaret() {
     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, adapter);
+    return ((CompilerReferenceServiceImpl)CompilerReferenceService.getInstance(myFixture.getProject())).getReferentFiles(memberAtCaret);
   }
 
   @Override
index a501e2fecd7a68b6d6c811853fdd178c2ea84a86..489a2ab6735c76c3e71d7b33190b80022a5496dd 100644 (file)
@@ -18,7 +18,7 @@ public class Javac8RefScanner extends JavacTreeRefScanner {
     JCTree.JCLambda lambda = (JCTree.JCLambda)node;
     final Type type = lambda.type;
     final Symbol.TypeSymbol symbol = type.asElement();
-    sink.sinkReference(new JavacRefSymbol(symbol, Tree.Kind.LAMBDA_EXPRESSION));
+    sink.sinkDeclaration(new JavacRefSymbol(symbol, Tree.Kind.LAMBDA_EXPRESSION));
     return super.visitLambdaExpression(node, sink);
   }
 
@@ -27,7 +27,7 @@ public class Javac8RefScanner extends JavacTreeRefScanner {
     JCTree.JCMemberReference memberRef = (JCTree.JCMemberReference)node;
     final Symbol methodSymbol = memberRef.sym;
     sink.sinkReference(new JavacRefSymbol(methodSymbol, Tree.Kind.IDENTIFIER));
-    sink.sinkReference(new JavacRefSymbol(memberRef.type.asElement(), Tree.Kind.MEMBER_REFERENCE));
+    sink.sinkDeclaration(new JavacRefSymbol(memberRef.type.asElement(), Tree.Kind.MEMBER_REFERENCE));
     return super.visitMemberReference(node, sink);
   }
 }
index 70c68c529132f3fc1c809fbccce9c108956d512c..14c71e8266103c0d9adbad80382b23537ddb0494 100644 (file)
@@ -1,14 +1,15 @@
 Backward Hierarchy:
 java.lang.Object -> Lambda
+java.lang.Runnable -> fun_expr(id=0)
 
 Backward References:
 Lambda in Lambda
 Lambda.<init>(0) in Lambda
 Lambda.main(1) in Lambda
-fun_expr(java.lang.Runnable) in Lambda
 java.lang.Object.<init>(0) in Lambda
 java.lang.String in Lambda
 java.lang.Thread in Lambda
 
 Class Definitions:
-Lambda in Lambda
\ No newline at end of file
+Lambda in Lambda
+fun_expr(id=0) in Lambda
\ No newline at end of file
index 3bf4cae032469c2a99006dabf3bb9c9bdbe8acc1..6582ae188fcdcd33f029ce75d964a4cc87f70b57 100644 (file)
@@ -1,11 +1,11 @@
 Backward Hierarchy:
 java.lang.Object -> MethodReference
+java.lang.Runnable -> fun_expr(id=0)
 
 Backward References:
 MethodReference in MethodReference
 MethodReference.<init>(0) in MethodReference
 MethodReference.main(1) in MethodReference
-fun_expr(java.lang.Runnable) in MethodReference
 java.lang.Object.<init>(0) in MethodReference
 java.lang.String in MethodReference
 java.lang.Thread in MethodReference
@@ -13,4 +13,5 @@ java.util.Collections in MethodReference
 java.util.Collections.emptyList(0) in MethodReference
 
 Class Definitions:
-MethodReference in MethodReference
\ No newline at end of file
+MethodReference in MethodReference
+fun_expr(id=0) in MethodReference
\ No newline at end of file
index a66969609754f594de4ee58c14607186a1099572..51fa3972d9e51c1ff166d70f6ad57b6d69d507d8 100644 (file)
@@ -18,9 +18,12 @@ package org.jetbrains.jps.backwardRefs;
 import com.intellij.util.Function;
 import com.intellij.util.SystemProperties;
 import com.intellij.util.containers.ContainerUtil;
+import com.sun.source.tree.Tree;
+import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.code.Symbol;
 import gnu.trove.THashSet;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.jetbrains.jps.builders.java.JavaBuilderUtil;
 import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
 import org.jetbrains.jps.incremental.CompileContext;
@@ -37,6 +40,8 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
+import static com.sun.tools.javac.code.Flags.PRIVATE;
+
 public class BackwardReferenceIndexWriter {
   public static final String PROP_KEY = "ref.index.builder";
 
@@ -89,8 +94,8 @@ public class BackwardReferenceIndexWriter {
     return enumeratePath(file.getName());
   }
 
-  synchronized LightUsage.LightClassUsage asClassUsage(Symbol name) {
-    return new LightUsage.LightClassUsage(myIndex.getByteSeqEum().enumerate(LightUsage.bytes(name)));
+  synchronized LightRef.JavaLightClassRef asClassUsage(Symbol name) {
+    return new LightRef.JavaLightClassRef(myIndex.getByteSeqEum().enumerate(bytes(name)));
   }
 
   synchronized void processDeletedFiles(Collection<String> paths) {
@@ -98,22 +103,22 @@ public class BackwardReferenceIndexWriter {
       final int deletedFileId = enumeratePath(path);
 
       //remove from reference maps
-      final Collection<LightUsage> refs = myIndex.getReferenceMap().get(deletedFileId);
+      final Collection<LightRef> refs = myIndex.getReferenceMap().get(deletedFileId);
       if (refs != null) {
-        for (LightUsage ref : refs) {
+        for (LightRef ref : refs) {
           myIndex.getBackwardReferenceMap().removeFrom(ref, deletedFileId);
         }
       }
       myIndex.getReferenceMap().remove(deletedFileId);
 
       //remove from definition & hierarchy maps
-      final Collection<LightUsage> definedClasses = myIndex.getClassDefinitionMap().get(deletedFileId);
+      final Collection<LightRef> definedClasses = myIndex.getClassDefinitionMap().get(deletedFileId);
       removeClassesFromHierarchy(deletedFileId, definedClasses);
       myIndex.getClassDefinitionMap().remove(deletedFileId);
     }
   }
 
-  synchronized void writeClassDefinitions(int fileId, Collection<LightUsage> classes) {
+  synchronized void writeClassDefinitions(int fileId, Collection<LightRef> classes) {
     if (myRebuild) {
       directlyWriteClassDefinitions(fileId, classes);
     } else {
@@ -121,12 +126,12 @@ public class BackwardReferenceIndexWriter {
     }
   }
 
-  private void updateClassDefinitions(int fileId, Collection<LightUsage> classes) {
-    final Collection<LightUsage> oldDefs = myIndex.getClassDefinitionMap().get(fileId);
-    final Collection<LightUsage> oldDefsCopy = oldDefs == null ? null : new THashSet<LightUsage>(oldDefs);
+  private void updateClassDefinitions(int fileId, Collection<LightRef> classes) {
+    final Collection<LightRef> oldDefs = myIndex.getClassDefinitionMap().get(fileId);
+    final Collection<LightRef> oldDefsCopy = oldDefs == null ? null : new THashSet<LightRef>(oldDefs);
 
     myIndex.getClassDefinitionMap().replace(fileId, classes);
-    for (LightUsage aClass : classes) {
+    for (LightRef aClass : classes) {
       if (oldDefsCopy == null || !oldDefsCopy.remove(aClass)) {
         myIndex.getBackwardClassDefinitionMap().put(aClass, fileId);
       }
@@ -135,24 +140,24 @@ public class BackwardReferenceIndexWriter {
     removeClassesFromHierarchy(fileId, oldDefsCopy);
   }
 
-  private void directlyWriteClassDefinitions(int fileId, Collection<LightUsage> classes) {
+  private void directlyWriteClassDefinitions(int fileId, Collection<LightRef> classes) {
     myIndex.getClassDefinitionMap().put(fileId, classes);
-    for (LightUsage aClass : classes) {
+    for (LightRef aClass : classes) {
       myIndex.getBackwardClassDefinitionMap().put(aClass, fileId);
     }
   }
 
   synchronized void writeReferences(int fileId, Collection<JavacRefSymbol> refs) {
     final ByteArrayEnumerator byteSeqEum = myIndex.getByteSeqEum();
-    final List<LightUsage> usages = ContainerUtil.mapNotNull(refs, new Function<JavacRefSymbol, LightUsage>() {
+    final List<LightRef> usages = ContainerUtil.mapNotNull(refs, new Function<JavacRefSymbol, LightRef>() {
       @Override
-      public LightUsage fun(JavacRefSymbol symbol) {
-        return LightUsage.fromSymbol(symbol, byteSeqEum);
+      public LightRef fun(JavacRefSymbol symbol) {
+        return fromSymbol(symbol, byteSeqEum);
       }
     });
 
     if (myRebuild) {
-      for (LightUsage usage : usages) {
+      for (LightRef usage : usages) {
         myIndex.getBackwardReferenceMap().put(usage, fileId);
         myIndex.getReferenceMap().put(fileId, usage);
       }
@@ -162,10 +167,10 @@ public class BackwardReferenceIndexWriter {
     }
   }
 
-  private void updateReferenceIndicesIncrementally(int fileId, Collection<LightUsage> usages) {
-    final Collection<LightUsage> rawOldUsages = myIndex.getReferenceMap().get(fileId);
-    Collection<LightUsage> oldUsages = rawOldUsages == null ? null : new ArrayList<LightUsage>(rawOldUsages);
-    for (LightUsage usage : usages) {
+  private void updateReferenceIndicesIncrementally(int fileId, Collection<LightRef> usages) {
+    final Collection<LightRef> rawOldUsages = myIndex.getReferenceMap().get(fileId);
+    Collection<LightRef> oldUsages = rawOldUsages == null ? null : new ArrayList<LightRef>(rawOldUsages);
+    for (LightRef usage : usages) {
       if (oldUsages == null || !oldUsages.remove(usage)) {
         myIndex.getBackwardReferenceMap().put(usage, fileId);
         myIndex.getReferenceMap().put(fileId, usage);
@@ -173,13 +178,13 @@ public class BackwardReferenceIndexWriter {
     }
     if (oldUsages != null && !oldUsages.isEmpty()) {
       myIndex.getReferenceMap().removeAll(fileId, oldUsages);
-      for (LightUsage usage : oldUsages) {
+      for (LightRef usage : oldUsages) {
         myIndex.getBackwardReferenceMap().removeFrom(usage, fileId);
       }
     }
   }
 
-  synchronized void writeHierarchy(int fileId, LightUsage.LightClassUsage aClass, LightUsage.LightClassUsage[] supers) {
+  synchronized void writeHierarchy(int fileId, LightRef aClass, LightRef.JavaLightClassRef... supers) {
     CompilerBackwardReferenceIndex.LightDefinition def = new CompilerBackwardReferenceIndex.LightDefinition(aClass, fileId);
     if (myRebuild) {
       directlyWriteHierarchyIndices(def, supers);
@@ -198,17 +203,17 @@ public class BackwardReferenceIndexWriter {
     }
   }
 
-  private void directlyWriteHierarchyIndices(CompilerBackwardReferenceIndex.LightDefinition classId, LightUsage.LightClassUsage[] superIds) {
-    for (LightUsage.LightClassUsage superId : superIds) {
+  private void directlyWriteHierarchyIndices(CompilerBackwardReferenceIndex.LightDefinition classId, LightRef.JavaLightClassRef[] superIds) {
+    for (LightRef.JavaLightClassRef superId : superIds) {
       myIndex.getBackwardHierarchyMap().put(superId, classId);
       myIndex.getHierarchyMap().put(classId, superId);
     }
   }
 
-  private void updateHierarchyIndicesIncrementally(final CompilerBackwardReferenceIndex.LightDefinition classId, LightUsage.LightClassUsage[] superIds) {
-    final Collection<LightUsage> rawOldSupers = myIndex.getHierarchyMap().get(classId);
-    Set<LightUsage> oldSuperClasses = rawOldSupers == null ? null : new THashSet<LightUsage>(rawOldSupers);
-    for (LightUsage.LightClassUsage superId: superIds) {
+  private void updateHierarchyIndicesIncrementally(final CompilerBackwardReferenceIndex.LightDefinition classId, LightRef.JavaLightClassRef[] superIds) {
+    final Collection<LightRef> rawOldSupers = myIndex.getHierarchyMap().get(classId);
+    Set<LightRef> oldSuperClasses = rawOldSupers == null ? null : new THashSet<LightRef>(rawOldSupers);
+    for (LightRef.JavaLightClassRef superId: superIds) {
       if (oldSuperClasses == null || !oldSuperClasses.remove(superId)) {
         myIndex.getBackwardHierarchyMap().put(superId, classId);
         myIndex.getHierarchyMap().put(classId, superId);
@@ -216,22 +221,22 @@ public class BackwardReferenceIndexWriter {
     }
     if (oldSuperClasses != null && !oldSuperClasses.isEmpty()) {
       myIndex.getHierarchyMap().removeAll(classId, oldSuperClasses);
-      for (LightUsage anOldClass : oldSuperClasses) {
+      for (LightRef anOldClass : oldSuperClasses) {
         myIndex.getBackwardHierarchyMap().put(anOldClass, classId);
       }
     }
   }
 
 
-  private void removeClassesFromHierarchy(int deletedFileId, Collection<LightUsage> definedClasses) {
+  private void removeClassesFromHierarchy(int deletedFileId, Collection<LightRef> definedClasses) {
     if (definedClasses != null) {
-      for (LightUsage aClass : definedClasses) {
+      for (LightRef aClass : definedClasses) {
         myIndex.getBackwardClassDefinitionMap().removeFrom(aClass, deletedFileId);
         final CompilerBackwardReferenceIndex.LightDefinition def =
           new CompilerBackwardReferenceIndex.LightDefinition(aClass, deletedFileId);
-        final Collection<LightUsage> superClasses = myIndex.getHierarchyMap().get(def);
+        final Collection<LightRef> superClasses = myIndex.getHierarchyMap().get(def);
         if (superClasses != null) {
-          for (LightUsage superClass : superClasses) {
+          for (LightRef superClass : superClasses) {
             myIndex.getBackwardHierarchyMap().removeFrom(superClass, def);
           }
         }
@@ -239,6 +244,52 @@ public class BackwardReferenceIndexWriter {
       }
     }
   }
+
+  static byte[] bytes(Symbol symbol) {
+    return symbol.flatName().toUtf();
+  }
+
+  @Nullable
+  static LightRef fromSymbol(JavacRefSymbol refSymbol, ByteArrayEnumerator byteArrayEnumerator) {
+    Symbol symbol = refSymbol.getSymbol();
+    final Tree.Kind kind = refSymbol.getPlaceKind();
+    if (symbol instanceof Symbol.ClassSymbol) {
+      if (!isPrivate(symbol) && !isAnonymous(symbol)) {
+        return new LightRef.JavaLightClassRef(id(symbol, byteArrayEnumerator));
+      }
+    }
+    else {
+      Symbol owner = symbol.owner;
+      if (isPrivate(symbol)) {
+        return null;
+      }
+      if (symbol instanceof Symbol.VarSymbol) {
+        return new LightRef.JavaLightFieldRef(id(owner, byteArrayEnumerator), id(symbol, byteArrayEnumerator));
+      }
+      else if (symbol instanceof Symbol.MethodSymbol) {
+        int paramCount = ((Symbol.MethodSymbol)symbol).type.getParameterTypes().size();
+        return new LightRef.JavaLightMethodRef(id(owner, byteArrayEnumerator), id(symbol, byteArrayEnumerator), paramCount);
+      }
+      else {
+        throw new AssertionError("unexpected symbol: " + symbol + " class: " + symbol.getClass() + " kind: " + kind);
+      }
+    }
+    return null;
+  }
+
+  // JDK-6 has no Symbol.isPrivate() method
+  private static boolean isPrivate(Symbol symbol) {
+    return (symbol.flags() & Flags.AccessFlags) == PRIVATE;
+  }
+
+  // JDK-6 has no Symbol.isAnonymous() method
+  private static boolean isAnonymous(Symbol symbol) {
+    return symbol.name.isEmpty();
+  }
+
+  private static int id(Symbol symbol, ByteArrayEnumerator byteArrayEnumerator) {
+    return byteArrayEnumerator.enumerate(bytes(symbol));
+  }
 }
 
 
index 285969430a0ce16b5a0361fd4df82322d58c3387..550686a4b92f340bf645ac86febed3d982cdc237 100644 (file)
@@ -23,13 +23,28 @@ import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
 
 import javax.tools.*;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
 public class BackwardReferenceRegistrar implements JavacFileReferencesRegistrar {
   private static final Symbol[] EMPTY_SYMBOL_ARRAY = new Symbol[0];
 
+  private static final Tree.Kind LAMBDA_EXPRESSION;
+  private static final Tree.Kind MEMBER_REFERENCE;
+
+  static {
+    Tree.Kind lambdaExpression = null;
+    Tree.Kind memberReference = null;
+    try {
+      lambdaExpression = Tree.Kind.valueOf("LAMBDA_EXPRESSION");
+      memberReference = Tree.Kind.valueOf("MEMBER_REFERENCE");
+    }
+    catch (IllegalArgumentException ignored) {
+    }
+    LAMBDA_EXPRESSION = lambdaExpression;
+    MEMBER_REFERENCE = memberReference;
+  }
+
   private BackwardReferenceIndexWriter myWriter;
 
   @Override
@@ -44,10 +59,11 @@ public class BackwardReferenceRegistrar implements JavacFileReferencesRegistrar
   }
 
   @Override
-  public void registerFile(JavaFileObject file, Set<JavacRefSymbol> refs, Collection<JavacRefSymbol> defs) {
+  public void registerFile(JavaFileObject file, Set<JavacRefSymbol> refs, List<JavacRefSymbol> defs) {
     final int fileId = myWriter.enumerateFile(file);
+    int funExprId = 0;
 
-    final List<LightUsage> definedClasses = new ArrayList<LightUsage>(defs.size());
+    final List<LightRef> definitions = new ArrayList<LightRef>(defs.size());
     for (JavacRefSymbol def : defs) {
       Tree.Kind kind = def.getPlaceKind();
       if (kind == Tree.Kind.CLASS) {
@@ -68,24 +84,29 @@ public class BackwardReferenceRegistrar implements JavacFileReferencesRegistrar
           supers[i++] = anInterface.asElement();
         }
 
-
-        final LightUsage.LightClassUsage aClass = myWriter.asClassUsage(sym);
-        definedClasses.add(aClass);
+        final LightRef.JavaLightClassRef aClass = myWriter.asClassUsage(sym);
+        definitions.add(aClass);
 
         if (supers.length != 0) {
 
-          final LightUsage.LightClassUsage[] superIds = new LightUsage.LightClassUsage[supers.length];
+          final LightRef.JavaLightClassRef[] superIds = new LightRef.JavaLightClassRef[supers.length];
           for (int j = 0; j < supers.length; j++) {
             superIds[j] = myWriter.asClassUsage(supers[j]);
           }
 
           myWriter.writeHierarchy(fileId, aClass, superIds);
         }
-
+      }
+      else if (kind == LAMBDA_EXPRESSION || kind == MEMBER_REFERENCE) {
+        final LightRef.JavaLightClassRef functionalType = myWriter.asClassUsage(def.getSymbol());
+        int id = funExprId++;
+        LightRef.JavaLightFunExprDef result = new LightRef.JavaLightFunExprDef(id);
+        definitions.add(result);
+        myWriter.writeHierarchy(fileId, result, functionalType);
       }
     }
 
-    myWriter.writeClassDefinitions(fileId, definedClasses);
+    myWriter.writeClassDefinitions(fileId, definitions);
 
     myWriter.writeReferences(fileId, refs);
   }
index 6b0e38cfdb652194902b9c7c8267fedd8a2d8863..86efeb615c39ea0376c0dc6453bc1c5efbcafab9 100644 (file)
@@ -15,7 +15,9 @@
  */
 package org.jetbrains.jps.backwardRefs;
 
+import com.intellij.util.ObjectUtils;
 import com.intellij.util.io.*;
+import com.sun.tools.javac.util.Convert;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
@@ -64,6 +66,15 @@ public class ByteArrayEnumerator extends PersistentEnumeratorDelegate<byte[]> {
     if (myCache != null) myCache.close();
   }
 
+  @NotNull
+  public String getName(int idx) {
+    try {
+      return Convert.utf2string(ObjectUtils.notNull(valueOf(idx)));
+    }
+    catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
 
   private static class ByteSequenceDataExternalizer implements KeyDescriptor<byte[]>, DifferentSerializableBytesImplyNonEqualityPolicy {
     private static final ByteSequenceDataExternalizer INSTANCE = new ByteSequenceDataExternalizer();
index f603863a38cbb9174a8304ba10d9aec631457b30..e587eb0586e246cbe15a8a52fb44c88ac9189962 100644 (file)
@@ -45,14 +45,14 @@ public class CompilerBackwardReferenceIndex {
   private final static String BACK_CLASS_DEF_TAB = "back.class.def.tab";
   public static final String VERSION_FILE = ".version";
 
-  private final IntObjectPersistentMultiMaplet<LightUsage> myReferenceMap;
-  private final ObjectObjectPersistentMultiMaplet<LightDefinition, LightUsage> myHierarchyMap;
+  private final IntObjectPersistentMultiMaplet<LightRef> myReferenceMap;
+  private final ObjectObjectPersistentMultiMaplet<LightDefinition, LightRef> myHierarchyMap;
 
-  private final ObjectObjectPersistentMultiMaplet<LightUsage, Integer> myBackwardReferenceMap;
-  private final ObjectObjectPersistentMultiMaplet<LightUsage, LightDefinition> myBackwardHierarchyMap;
+  private final ObjectObjectPersistentMultiMaplet<LightRef, Integer> myBackwardReferenceMap;
+  private final ObjectObjectPersistentMultiMaplet<LightRef, LightDefinition> myBackwardHierarchyMap;
 
-  private final ObjectObjectPersistentMultiMaplet<LightUsage, Integer> myBackwardClassDefinitionMap;
-  private final IntObjectPersistentMultiMaplet<LightUsage> myClassDefinitionMap;
+  private final ObjectObjectPersistentMultiMaplet<LightRef, Integer> myBackwardClassDefinitionMap;
+  private final IntObjectPersistentMultiMaplet<LightRef> myClassDefinitionMap;
 
   private final ByteArrayEnumerator myNameEnumerator;
   private final PersistentStringEnumerator myFilePathEnumerator;
@@ -76,22 +76,22 @@ public class CompilerBackwardReferenceIndex {
         }
       };
 
-      final KeyDescriptor<LightUsage> lightUsageDescriptor = LightUsage.createDescriptor();
+      final KeyDescriptor<LightRef> lightUsageDescriptor = new LightRefDescriptor();
       final KeyDescriptor<LightDefinition> defDescriptor = LightDefinition.createDescriptor(lightUsageDescriptor);
 
-      myBackwardReferenceMap = new ObjectObjectPersistentMultiMaplet<LightUsage, Integer>(new File(myIndicesDir, BACK_USAGES_TAB),
-                                                                                          lightUsageDescriptor,
-                                                                                          EnumeratorIntegerDescriptor.INSTANCE,
-                                                                                          new CollectionFactory<Integer>() {
+      myBackwardReferenceMap = new ObjectObjectPersistentMultiMaplet<LightRef, Integer>(new File(myIndicesDir, BACK_USAGES_TAB),
+                                                                                        lightUsageDescriptor,
+                                                                                        EnumeratorIntegerDescriptor.INSTANCE,
+                                                                                        new CollectionFactory<Integer>() {
                                                                                         @Override
                                                                                         public Collection<Integer> create() {
                                                                                           return new THashSet<Integer>();
                                                                                         }
                                                                                       });
-      myBackwardHierarchyMap = new ObjectObjectPersistentMultiMaplet<LightUsage, LightDefinition>(new File(myIndicesDir, BACK_HIERARCHY_TAB),
-                                                                                                  lightUsageDescriptor,
-                                                                                                  defDescriptor,
-                                                                                                  new CollectionFactory<LightDefinition>() {
+      myBackwardHierarchyMap = new ObjectObjectPersistentMultiMaplet<LightRef, LightDefinition>(new File(myIndicesDir, BACK_HIERARCHY_TAB),
+                                                                                                lightUsageDescriptor,
+                                                                                                defDescriptor,
+                                                                                                new CollectionFactory<LightDefinition>() {
                                                                        @Override
                                                                        public Collection<LightDefinition> create() {
                                                                          return new THashSet<LightDefinition>();
@@ -99,38 +99,38 @@ public class CompilerBackwardReferenceIndex {
                                                                      });
 
 
-      myReferenceMap = new IntObjectPersistentMultiMaplet<LightUsage>(new File(myIndicesDir, USAGES_TAB),
-                                                                      EnumeratorIntegerDescriptor.INSTANCE,
-                                                                      lightUsageDescriptor, new CollectionFactory<LightUsage>() {
+      myReferenceMap = new IntObjectPersistentMultiMaplet<LightRef>(new File(myIndicesDir, USAGES_TAB),
+                                                                    EnumeratorIntegerDescriptor.INSTANCE,
+                                                                    lightUsageDescriptor, new CollectionFactory<LightRef>() {
         @Override
-        public Collection<LightUsage> create() {
-          return new THashSet<LightUsage>();
+        public Collection<LightRef> create() {
+          return new THashSet<LightRef>();
         }
       });
-      myHierarchyMap = new ObjectObjectPersistentMultiMaplet<LightDefinition, LightUsage>(new File(myIndicesDir, HIERARCHY_TAB),
-                                                                                     defDescriptor,
-                                                                                     lightUsageDescriptor,
-                                                                                     new CollectionFactory<LightUsage>() {
+      myHierarchyMap = new ObjectObjectPersistentMultiMaplet<LightDefinition, LightRef>(new File(myIndicesDir, HIERARCHY_TAB),
+                                                                                        defDescriptor,
+                                                                                        lightUsageDescriptor,
+                                                                                        new CollectionFactory<LightRef>() {
                                                                                        @Override
-                                                                                       public Collection<LightUsage> create() {
-                                                                                         return new THashSet<LightUsage>();
+                                                                                       public Collection<LightRef> create() {
+                                                                                         return new THashSet<LightRef>();
                                                                                        }
                                                                                      });
 
-      myClassDefinitionMap = new IntObjectPersistentMultiMaplet<LightUsage>(new File(myIndicesDir, CLASS_DEF_TAB),
-                                                                            EnumeratorIntegerDescriptor.INSTANCE,
-                                                                            lightUsageDescriptor,
-                                                                            new CollectionFactory<LightUsage>() {
+      myClassDefinitionMap = new IntObjectPersistentMultiMaplet<LightRef>(new File(myIndicesDir, CLASS_DEF_TAB),
+                                                                          EnumeratorIntegerDescriptor.INSTANCE,
+                                                                          lightUsageDescriptor,
+                                                                          new CollectionFactory<LightRef>() {
                                                                                     @Override
-                                                                                    public Collection<LightUsage> create() {
-                                                                                      return new THashSet<LightUsage>();
+                                                                                    public Collection<LightRef> create() {
+                                                                                      return new THashSet<LightRef>();
                                                                                     }
                                                                                   });
 
-      myBackwardClassDefinitionMap = new ObjectObjectPersistentMultiMaplet<LightUsage, Integer>(new File(myIndicesDir, BACK_CLASS_DEF_TAB),
-                                                                                                lightUsageDescriptor,
-                                                                                                EnumeratorIntegerDescriptor.INSTANCE,
-                                                                                                new CollectionFactory<Integer>() {
+      myBackwardClassDefinitionMap = new ObjectObjectPersistentMultiMaplet<LightRef, Integer>(new File(myIndicesDir, BACK_CLASS_DEF_TAB),
+                                                                                              lightUsageDescriptor,
+                                                                                              EnumeratorIntegerDescriptor.INSTANCE,
+                                                                                              new CollectionFactory<Integer>() {
                                                                                                         @Override
                                                                                                         public Collection<Integer> create() {
                                                                                                           return new THashSet<Integer>();
@@ -146,32 +146,32 @@ public class CompilerBackwardReferenceIndex {
   }
 
   @NotNull
-  public ObjectObjectPersistentMultiMaplet<LightUsage, Integer> getBackwardReferenceMap() {
+  public ObjectObjectPersistentMultiMaplet<LightRef, Integer> getBackwardReferenceMap() {
     return myBackwardReferenceMap;
   }
 
   @NotNull
-  public ObjectObjectPersistentMultiMaplet<LightUsage, LightDefinition> getBackwardHierarchyMap() {
+  public ObjectObjectPersistentMultiMaplet<LightRef, LightDefinition> getBackwardHierarchyMap() {
     return myBackwardHierarchyMap;
   }
 
   @NotNull
-  public IntObjectPersistentMultiMaplet<LightUsage> getReferenceMap() {
+  public IntObjectPersistentMultiMaplet<LightRef> getReferenceMap() {
     return myReferenceMap;
   }
 
   @NotNull
-  public ObjectObjectPersistentMultiMaplet<LightDefinition, LightUsage> getHierarchyMap() {
+  public ObjectObjectPersistentMultiMaplet<LightDefinition, LightRef> getHierarchyMap() {
     return myHierarchyMap;
   }
 
   @NotNull
-  public ObjectObjectPersistentMultiMaplet<LightUsage, Integer> getBackwardClassDefinitionMap() {
+  public ObjectObjectPersistentMultiMaplet<LightRef, Integer> getBackwardClassDefinitionMap() {
     return myBackwardClassDefinitionMap;
   }
 
   @NotNull
-  public IntObjectPersistentMultiMaplet<LightUsage> getClassDefinitionMap() {
+  public IntObjectPersistentMultiMaplet<LightRef> getClassDefinitionMap() {
     return myClassDefinitionMap;
   }
 
@@ -247,15 +247,15 @@ public class CompilerBackwardReferenceIndex {
   }
 
   public static class LightDefinition {
-    private final LightUsage myUsage;
+    private final LightRef myUsage;
     private final int myFileId;
 
-    LightDefinition(LightUsage usage, int id) {
+    LightDefinition(LightRef usage, int id) {
       myUsage = usage;
       myFileId = id;
     }
 
-    public LightUsage getUsage() {
+    public LightRef getRef() {
       return myUsage;
     }
 
@@ -281,7 +281,7 @@ public class CompilerBackwardReferenceIndex {
       return myUsage.hashCode();
     }
 
-    private static KeyDescriptor<LightDefinition> createDescriptor(final DataExternalizer<LightUsage> usageDataExternalizer) {
+    private static KeyDescriptor<LightDefinition> createDescriptor(final DataExternalizer<LightRef> usageDataExternalizer) {
       return new KeyDescriptor<LightDefinition>() {
         @Override
         public int getHashCode(LightDefinition value) {
@@ -295,7 +295,7 @@ public class CompilerBackwardReferenceIndex {
 
         @Override
         public void save(@NotNull DataOutput out, LightDefinition value) throws IOException {
-          usageDataExternalizer.save(out, value.getUsage());
+          usageDataExternalizer.save(out, value.getRef());
           EnumeratorIntegerDescriptor.INSTANCE.save(out, value.getFileId());
         }
 
diff --git a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/LightRef.java b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/LightRef.java
new file mode 100644 (file)
index 0000000..3b94591
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * 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.intellij.util.io.DataInputOutputUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.java.dependencyView.RW;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+public interface LightRef extends RW.Savable {
+  LightRef[] EMPTY_ARRAY = new LightRef[0];
+
+  byte CLASS_MARKER = 0x0;
+  byte METHOD_MARKER = 0x1;
+  byte FIELD_MARKER = 0x2;
+  byte FUN_EXPR_MARKER = 0x3;
+
+  LightRef override(int newOwner);
+
+  interface NamedLightRef extends LightRef {
+    int getName();
+  }
+
+  interface LightClassHierarchyElementDef extends NamedLightRef {
+  }
+
+  interface LightFunExprDef extends LightRef {
+    int getId();
+  }
+
+  interface LightMember extends NamedLightRef {
+    @NotNull
+    LightClassHierarchyElementDef getOwner();
+  }
+
+  class JavaLightMethodRef implements LightMember {
+    private final int myOwner;
+    private final int myName;
+    private final int myParameterCount;
+
+    public JavaLightMethodRef(int owner, int name, int parameterCount) {
+      myOwner = owner;
+      myName = name;
+      myParameterCount = parameterCount;
+    }
+
+    public int getName() {
+      return myName;
+    }
+
+    @Override
+    public LightRef override(int newOwner) {
+      return new JavaLightMethodRef(newOwner, myName, myParameterCount);
+    }
+
+    public int getParameterCount() {
+      return myParameterCount;
+    }
+
+    @Override
+    @NotNull
+    public LightClassHierarchyElementDef getOwner() {
+      return new JavaLightClassRef(myOwner);
+    }
+
+    @Override
+    public void save(DataOutput out) {
+      try {
+        out.writeByte(METHOD_MARKER);
+        DataInputOutputUtil.writeINT(out, myOwner);
+        DataInputOutputUtil.writeINT(out, getName());
+        DataInputOutputUtil.writeINT(out, getParameterCount());
+      }
+      catch (IOException e) {
+        throw new BuildDataCorruptedException(e);
+      }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      JavaLightMethodRef usage = (JavaLightMethodRef)o;
+
+      if (myOwner != usage.myOwner) return false;
+      if (myName != usage.myName) return false;
+      if (myParameterCount != usage.myParameterCount) return false;
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      int result = myName;
+      result = 31 * result + myParameterCount;
+      result = 31 * result + myOwner;
+      return result;
+    }
+  }
+
+  class JavaLightFieldRef implements LightMember {
+    private final int myOwner;
+    private final int myName;
+
+    public JavaLightFieldRef(int owner, int name) {
+      myOwner = owner;
+      myName = name;
+    }
+
+    @Override
+    public int getName() {
+      return myName;
+    }
+
+    @Override
+    public LightRef override(int newOwner) {
+      return new JavaLightFieldRef(newOwner, myName);
+    }
+
+    @NotNull
+    @Override
+    public LightClassHierarchyElementDef getOwner() {
+      return new JavaLightClassRef(myOwner);
+    }
+
+    @Override
+    public void save(DataOutput out) {
+      try {
+        out.writeByte(FIELD_MARKER);
+        DataInputOutputUtil.writeINT(out, myOwner);
+        DataInputOutputUtil.writeINT(out, getName());
+      }
+      catch (IOException e) {
+        throw new BuildDataCorruptedException(e);
+      }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      JavaLightFieldRef usage = (JavaLightFieldRef)o;
+
+      if (myOwner != usage.myOwner) return false;
+      if (myName != usage.myName) return false;
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return myName + 31 * myOwner;
+    }
+  }
+
+  class JavaLightClassRef implements LightClassHierarchyElementDef {
+    private final int myName;
+
+    public JavaLightClassRef(int name) {
+      myName = name;
+    }
+
+    @Override
+    public int getName() {
+      return myName;
+    }
+
+    @Override
+    public LightRef override(int newOwner) {
+      return new JavaLightClassRef(newOwner);
+    }
+
+    @Override
+    public void save(DataOutput out) {
+      try {
+        out.writeByte(CLASS_MARKER);
+        DataInputOutputUtil.writeINT(out, getName());
+      }
+      catch (IOException e) {
+        throw new BuildDataCorruptedException(e);
+      }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      JavaLightClassRef usage = (JavaLightClassRef)o;
+
+      if (myName != usage.myName) return false;
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return myName;
+    }
+  }
+
+  class JavaLightFunExprDef implements LightFunExprDef {
+    private final int myId;
+
+    public JavaLightFunExprDef(int id) {
+      myId = id;
+    }
+
+    @Override
+    public int getId() {
+      return myId;
+    }
+
+    @Override
+    public LightRef override(int newOwner) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void save(DataOutput out) {
+      try {
+        out.writeByte(FUN_EXPR_MARKER);
+        DataInputOutputUtil.writeINT(out, getId());
+      }
+      catch (IOException e) {
+        throw new BuildDataCorruptedException(e);
+      }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      JavaLightFunExprDef usage = (JavaLightFunExprDef)o;
+      return myId == usage.myId;
+    }
+
+    @Override
+    public int hashCode() {
+      return myId;
+    }
+
+  }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/LightRefDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/LightRefDescriptor.java
new file mode 100644 (file)
index 0000000..9734b2f
--- /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 org.jetbrains.jps.backwardRefs;
+
+import com.intellij.util.io.DataInputOutputUtil;
+import com.intellij.util.io.DifferentSerializableBytesImplyNonEqualityPolicy;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import static org.jetbrains.jps.backwardRefs.LightRef.*;
+
+final class LightRefDescriptor implements KeyDescriptor<LightRef>, DifferentSerializableBytesImplyNonEqualityPolicy {
+  @Override
+  public int getHashCode(LightRef value) {
+    return value.hashCode();
+  }
+
+  @Override
+  public boolean isEqual(LightRef val1, LightRef val2) {
+    return val1.equals(val2);
+  }
+
+  @Override
+  public void save(@NotNull DataOutput out, LightRef value) throws IOException {
+    value.save(out);
+  }
+
+  @Override
+  public LightRef read(@NotNull DataInput in) throws IOException {
+    final byte type = in.readByte();
+    switch (type) {
+      case CLASS_MARKER:
+        return new JavaLightClassRef(DataInputOutputUtil.readINT(in));
+      case METHOD_MARKER:
+        return new JavaLightMethodRef(DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in));
+      case FIELD_MARKER:
+        return new JavaLightFieldRef(DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in));
+      case FUN_EXPR_MARKER:
+        return new JavaLightFunExprDef(DataInputOutputUtil.readINT(in));
+    }
+    throw new AssertionError();
+  }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/LightUsage.java b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/LightUsage.java
deleted file mode 100644 (file)
index 589e523..0000000
+++ /dev/null
@@ -1,380 +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.intellij.util.io.DataInputOutputUtil;
-import com.intellij.util.io.KeyDescriptor;
-import com.sun.source.tree.Tree;
-import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Symbol;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jps.builders.java.dependencyView.RW;
-import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
-import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-import static com.sun.tools.javac.code.Flags.PRIVATE;
-
-public abstract class LightUsage implements RW.Savable {
-  private final static byte CLASS_MARKER = 0x0;
-  private final static byte METHOD_MARKER = 0x1;
-  private final static byte FIELD_MARKER = 0x2;
-  private final static byte FUN_EXPR_MARKER = 0x3;
-
-  static final Tree.Kind LAMBDA_EXPRESSION;
-  static final Tree.Kind MEMBER_REFERENCE;
-
-  static {
-    Tree.Kind lambdaExpression = null;
-    Tree.Kind memberReference = null;
-    try {
-      lambdaExpression = Tree.Kind.valueOf("LAMBDA_EXPRESSION");
-      memberReference = Tree.Kind.valueOf("MEMBER_REFERENCE");
-    }
-    catch (IllegalArgumentException ignored) {
-    }
-    LAMBDA_EXPRESSION = lambdaExpression;
-    MEMBER_REFERENCE = memberReference;
-  }
-
-  public abstract int getName();
-
-  @NotNull
-  public abstract LightUsage override(LightUsage overriderClass);
-
-  @NotNull
-  public abstract LightUsage getOwner();
-
-  public static class LightMethodUsage extends LightUsage {
-    private final int myOwner;
-    private final int myName;
-    private final int myParameterCount;
-
-    public LightMethodUsage(int owner, int name, int parameterCount) {
-      myOwner = owner;
-      myName = name;
-      myParameterCount = parameterCount;
-    }
-
-    @Override
-    public int getName() {
-      return myName;
-    }
-
-    public int getParameterCount() {
-      return myParameterCount;
-    }
-
-    @Override
-    @NotNull
-    public LightUsage getOwner() {
-      return new LightClassUsage(myOwner);
-    }
-
-    @Override
-    public void save(DataOutput out) {
-      try {
-        out.writeByte(METHOD_MARKER);
-        DataInputOutputUtil.writeINT(out, myOwner);
-        DataInputOutputUtil.writeINT(out, getName());
-        DataInputOutputUtil.writeINT(out, getParameterCount());
-      }
-      catch (IOException e) {
-        throw new BuildDataCorruptedException(e);
-      }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-      if (this == o) return true;
-      if (o == null || getClass() != o.getClass()) return false;
-
-      LightMethodUsage usage = (LightMethodUsage)o;
-
-      if (myOwner != usage.myOwner) return false;
-      if (myName != usage.myName) return false;
-      if (myParameterCount != usage.myParameterCount) return false;
-
-      return true;
-    }
-
-    @Override
-    public int hashCode() {
-      int result = myName;
-      result = 31 * result + myParameterCount;
-      result = 31 * result + myOwner;
-      return result;
-    }
-
-    @NotNull
-    @Override
-    public LightMethodUsage override(LightUsage overriderClass) {
-      return new LightMethodUsage(overriderClass.getName(), getName(), getParameterCount());
-    }
-  }
-
-  public static class LightFieldUsage extends LightUsage {
-    private final int myOwner;
-    private final int myName;
-
-    public LightFieldUsage(int owner, int name) {
-      myOwner = owner;
-      myName = name;
-    }
-
-    @Override
-    public int getName() {
-      return myName;
-    }
-
-    @NotNull
-    @Override
-    public LightUsage getOwner() {
-      return new LightClassUsage(myOwner);
-    }
-
-    @Override
-    public void save(DataOutput out) {
-      try {
-        out.writeByte(FIELD_MARKER);
-        DataInputOutputUtil.writeINT(out, myOwner);
-        DataInputOutputUtil.writeINT(out, getName());
-      }
-      catch (IOException e) {
-        throw new BuildDataCorruptedException(e);
-      }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-      if (this == o) return true;
-      if (o == null || getClass() != o.getClass()) return false;
-
-      LightFieldUsage usage = (LightFieldUsage)o;
-
-      if (myOwner != usage.myOwner) return false;
-      if (myName != usage.myName) return false;
-
-      return true;
-    }
-
-    @Override
-    public int hashCode() {
-      return myName + 31 * myOwner;
-    }
-
-    @NotNull
-    @Override
-    public LightFieldUsage override(LightUsage overriderClass) {
-      return new LightFieldUsage(overriderClass.getName(), getName());
-    }
-
-  }
-
-  public static class LightClassUsage extends LightUsage {
-    private final int myName;
-
-    public LightClassUsage(int name) {
-      myName = name;
-    }
-
-    @Override
-    public int getName() {
-      return myName;
-    }
-
-    @NotNull
-    @Override
-    public LightClassUsage override(LightUsage overriderClass) {
-      return (LightClassUsage)overriderClass;
-    }
-
-    @NotNull
-    @Override
-    public LightUsage getOwner() {
-      return this;
-    }
-
-
-    @Override
-    public void save(DataOutput out) {
-      try {
-        out.writeByte(CLASS_MARKER);
-        DataInputOutputUtil.writeINT(out, getName());
-      }
-      catch (IOException e) {
-        throw new BuildDataCorruptedException(e);
-      }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-      if (this == o) return true;
-      if (o == null || getClass() != o.getClass()) return false;
-
-      LightClassUsage usage = (LightClassUsage)o;
-
-      if (myName != usage.myName) return false;
-
-      return true;
-    }
-
-    @Override
-    public int hashCode() {
-      return myName;
-    }
-  }
-
-  public static class LightFunExprUsage extends LightUsage {
-    private final int myName;
-
-    public LightFunExprUsage(int name) {
-      myName = name;
-    }
-
-    @NotNull
-    @Override
-    public LightFunExprUsage override(LightUsage overriderClass) {
-      throw new UnsupportedOperationException();
-    }
-
-    @NotNull
-    @Override
-    public LightUsage getOwner() {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int getName() {
-      return myName;
-    }
-
-    @Override
-    public void save(DataOutput out) {
-      try {
-        out.writeByte(FUN_EXPR_MARKER);
-        DataInputOutputUtil.writeINT(out, getName());
-      }
-      catch (IOException e) {
-        throw new BuildDataCorruptedException(e);
-      }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-      if (this == o) return true;
-      if (o == null || getClass() != o.getClass()) return false;
-
-      LightFunExprUsage usage = (LightFunExprUsage)o;
-
-      if (myName != usage.myName) return false;
-
-      return true;
-    }
-
-    @Override
-    public int hashCode() {
-      return myName;
-    }
-  }
-
-  static KeyDescriptor<LightUsage> createDescriptor() {
-    return new KeyDescriptor<LightUsage>() {
-      @Override
-      public int getHashCode(LightUsage value) {
-        return value.hashCode();
-      }
-
-      @Override
-      public boolean isEqual(LightUsage val1, LightUsage val2) {
-        return val1.equals(val2);
-      }
-
-      @Override
-      public void save(@NotNull DataOutput out, LightUsage value) throws IOException {
-        value.save(out);
-      }
-
-      @Override
-      public LightUsage read(@NotNull DataInput in) throws IOException {
-        final byte type = in.readByte();
-        switch (type) {
-          case CLASS_MARKER:
-            return new LightClassUsage(DataInputOutputUtil.readINT(in));
-          case METHOD_MARKER:
-            return new LightMethodUsage(DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in));
-          case FIELD_MARKER:
-            return new LightFieldUsage(DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in));
-          case FUN_EXPR_MARKER:
-            return new LightFunExprUsage(DataInputOutputUtil.readINT(in));
-        }
-        throw new AssertionError();
-      }
-    };
-  }
-
-  static byte[] bytes(Symbol symbol) {
-    return symbol.flatName().toUtf();
-  }
-
-  @Nullable
-  static LightUsage fromSymbol(JavacRefSymbol refSymbol, ByteArrayEnumerator byteArrayEnumerator) {
-    Symbol symbol = refSymbol.getSymbol();
-    final Tree.Kind kind = refSymbol.getPlaceKind();
-    if (symbol instanceof Symbol.ClassSymbol) {
-      if (kind == LAMBDA_EXPRESSION || kind == MEMBER_REFERENCE) {
-        return new LightFunExprUsage(id(symbol, byteArrayEnumerator));
-      } else if (!isPrivate(symbol) && !isAnonymous(symbol)) {
-        return new LightClassUsage(id(symbol, byteArrayEnumerator));
-      }
-    }
-    else {
-      Symbol owner = symbol.owner;
-      if (isPrivate(symbol)) {
-        return null;
-      }
-      if (symbol instanceof Symbol.VarSymbol) {
-        return new LightFieldUsage(id(owner, byteArrayEnumerator), id(symbol, byteArrayEnumerator));
-      }
-      else if (symbol instanceof Symbol.MethodSymbol) {
-        int paramCount = ((Symbol.MethodSymbol)symbol).type.getParameterTypes().size();
-        return new LightMethodUsage(id(owner, byteArrayEnumerator), id(symbol, byteArrayEnumerator), paramCount);
-      }
-      else {
-        throw new AssertionError("unexpected symbol: " + symbol + " class: " + symbol.getClass() + " kind: " + kind);
-      }
-    }
-    return null;
-  }
-
-  // JDK-6 has no Symbol.isPrivate() method
-  private static boolean isPrivate(Symbol symbol) {
-    return (symbol.flags() & Flags.AccessFlags) == PRIVATE;
-  }
-
-  // JDK-6 has no Symbol.isAnonymous() method
-  private static boolean isAnonymous(Symbol symbol) {
-    return symbol.name.isEmpty();
-  }
-
-  private static int id(Symbol symbol, ByteArrayEnumerator byteArrayEnumerator) {
-    return byteArrayEnumerator.enumerate(bytes(symbol));
-  }
-}
index 6a597ba4fc443ca0dc984e5619bff2b93e77c3ca..f461708dfe213f1642ad2c3adcee126d87ae1715 100644 (file)
@@ -32,10 +32,11 @@ import org.jetbrains.jps.service.JpsServiceManager;
 
 import javax.lang.model.element.ElementKind;
 import javax.lang.model.element.TypeElement;
-import javax.tools.*;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
 
 public class JavacReferencesCollector {
   public static void installOn(JavacTask task) {
@@ -76,12 +77,12 @@ public class JavacReferencesCollector {
     private final JavacFileReferencesRegistrar[] myOnlyImportsListeners;
     private final JavacTreeRefScanner myAstScanner;
 
-    private Name myAsteriks;
+    private Name myAsterisk;
 
-    private int myRemainDecls;
+    private int myRemainDeclarations;
     private JCTree.JCCompilationUnit myCurrentCompilationUnit;
     private Set<JavacRefSymbol> myCollectedReferences;
-    private Set<JavacRefSymbol> myCollectedDefinitions;
+    private List<JavacRefSymbol> myCollectedDefinitions;
 
     public MyTaskListener(JavacFileReferencesRegistrar[] fullASTListenerArray, JavacFileReferencesRegistrar[] importsListenerArray) {
       myFullASTListeners = fullASTListenerArray;
@@ -101,16 +102,16 @@ public class JavacReferencesCollector {
           // javac creates an event on each processed top level declared class not file
           if (myCurrentCompilationUnit != e.getCompilationUnit()) {
             myCurrentCompilationUnit = (JCTree.JCCompilationUnit)e.getCompilationUnit();
-            myCollectedDefinitions = new THashSet<JavacRefSymbol>();
+            myCollectedDefinitions = new ArrayList<JavacRefSymbol>();
             myCollectedReferences = new THashSet<JavacRefSymbol>();
-            myRemainDecls = myCurrentCompilationUnit.getTypeDecls().size() - 1;
+            myRemainDeclarations = myCurrentCompilationUnit.getTypeDecls().size() - 1;
             scanImports(myCurrentCompilationUnit, myCollectedReferences);
             for(JavacFileReferencesRegistrar r: myOnlyImportsListeners) {
               r.registerFile(e.getSourceFile(), myCollectedReferences, myCollectedDefinitions);
             }
           }
           else {
-            myRemainDecls--;
+            myRemainDeclarations--;
           }
 
           JavacTreeScannerSink sink = new JavacTreeScannerSink() {
@@ -134,7 +135,7 @@ public class JavacReferencesCollector {
             }
           }
 
-          if (myRemainDecls == 0) {
+          if (myRemainDeclarations == 0) {
             if (myFullASTListeners.length != 0) {
               for (JCTree.JCAnnotation annotation : myCurrentCompilationUnit.getPackageAnnotations()) {
                 myAstScanner.scan(annotation, sink);
@@ -158,10 +159,10 @@ public class JavacReferencesCollector {
     }
 
     private Name getAsteriskFromCurrentNameTable(Name tableRepresentative) {
-      if (myAsteriks == null) {
-        myAsteriks = tableRepresentative.table.fromChars(new char[]{'*'}, 0, 1);
+      if (myAsterisk == null) {
+        myAsterisk = tableRepresentative.table.fromChars(new char[]{'*'}, 0, 1);
       }
-      return myAsteriks;
+      return myAsterisk;
     }
 
     private void scanImports(JCTree.JCCompilationUnit compilationUnit, Set<JavacRefSymbol> symbols) {
index 8498ba7057c69d9cca90a91def678b80d9eae9bf..b03f0e1e813ee146bd657809b62f5ca585d8ae8b 100644 (file)
@@ -16,7 +16,7 @@
 package org.jetbrains.jps.javac.ast.api;
 
 import javax.tools.*;
-import java.util.Collection;
+import java.util.List;
 import java.util.Set;
 
 public interface JavacFileReferencesRegistrar {
@@ -25,5 +25,5 @@ public interface JavacFileReferencesRegistrar {
 
   boolean onlyImports();
 
-  void registerFile(JavaFileObject file, Set<JavacRefSymbol> refs, Collection<JavacRefSymbol> defs);
+  void registerFile(JavaFileObject file, Set<JavacRefSymbol> refs, List<JavacRefSymbol> defs);
 }
index 3d96dd828fc289cdd9bab53018b97133a2c3cade..accc05100e94e9a22f1673d02afdeb4d0abb405f 100644 (file)
@@ -17,14 +17,13 @@ package org.jetbrains.references
 
 import com.intellij.openapi.util.io.FileUtil
 import com.intellij.openapi.vfs.CharsetToolkit
-import com.intellij.openapi.vfs.VfsUtil
 import com.intellij.util.PathUtil
 import com.intellij.util.io.PersistentStringEnumerator
 import com.sun.tools.javac.util.Convert
 import org.jetbrains.jps.backwardRefs.BackwardReferenceIndexWriter
 import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator
 import org.jetbrains.jps.backwardRefs.CompilerBackwardReferenceIndex
-import org.jetbrains.jps.backwardRefs.LightUsage
+import org.jetbrains.jps.backwardRefs.LightRef
 import org.jetbrains.jps.builders.JpsBuildTestCase
 import org.jetbrains.jps.builders.TestProjectBuilderLogger
 import org.jetbrains.jps.builders.logging.BuildLoggingManager
@@ -135,15 +134,14 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
 
   private fun Int.asName(byteArrayEnumerator: ByteArrayEnumerator): String = Convert.utf2string(byteArrayEnumerator.valueOf(this))
 
-  private fun CompilerBackwardReferenceIndex.LightDefinition.asText(byteArrayEnumerator: ByteArrayEnumerator) = this.usage.asText(byteArrayEnumerator)
+  private fun CompilerBackwardReferenceIndex.LightDefinition.asText(byteArrayEnumerator: ByteArrayEnumerator) = this.ref.asText(byteArrayEnumerator)
 
-  private fun LightUsage.asText(byteArrayEnumerator: ByteArrayEnumerator): String =
+  private fun LightRef.asText(byteArrayEnumerator: ByteArrayEnumerator): String =
       when (this) {
-        is LightUsage.LightMethodUsage -> this.owner.name.asName(byteArrayEnumerator) + "." + this.name.asName(
-            byteArrayEnumerator) + "(" + this.parameterCount + ")"
-        is LightUsage.LightFieldUsage -> this.owner.name.asName(byteArrayEnumerator) + "." + this.name.asName(byteArrayEnumerator)
-        is LightUsage.LightClassUsage -> this.name.asName(byteArrayEnumerator)
-        is LightUsage.LightFunExprUsage -> "fun_expr(" + this.name.asName(byteArrayEnumerator) + ")"
+        is LightRef.JavaLightMethodRef -> "${this.owner.name.asName(byteArrayEnumerator)}.${this.name.asName(byteArrayEnumerator)}(${this.parameterCount})"
+        is LightRef.JavaLightFieldRef -> "${this.owner.name.asName(byteArrayEnumerator)}.${this.name.asName(byteArrayEnumerator)}"
+        is LightRef.JavaLightClassRef -> this.name.asName(byteArrayEnumerator)
+        is LightRef.JavaLightFunExprDef -> "fun_expr(id=${this.id})"
         else -> throw UnsupportedOperationException()
       }