Test light classes from sources have priority over decompiled light classes
This commit is contained in:
@@ -22,13 +22,12 @@ import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.SLRUCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -41,6 +40,7 @@ import org.jetbrains.kotlin.psi.JetFile;
|
||||
import org.jetbrains.kotlin.resolve.jvm.KotlinFinderMarker;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -121,7 +121,7 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
answer.addAll(lightClassGenerationSupport.getPackageClasses(qualifiedName.parent(), scope));
|
||||
}
|
||||
|
||||
return answer.toArray(new PsiClass[answer.size()]);
|
||||
return sortByClasspath(answer, scope).toArray(new PsiClass[answer.size()]);
|
||||
}
|
||||
|
||||
// Finds explicitly declared classes and objects, not package classes
|
||||
@@ -209,7 +209,7 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
}
|
||||
}
|
||||
|
||||
return answer.toArray(new PsiClass[answer.size()]);
|
||||
return sortByClasspath(answer, scope).toArray(new PsiClass[answer.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -268,4 +268,27 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
return fqName + " in " + scope;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Comparator<PsiElement> byClasspathComparator(@NotNull final GlobalSearchScope searchScope) {
|
||||
return new Comparator<PsiElement>() {
|
||||
@Override
|
||||
public int compare(@NotNull PsiElement o1, @NotNull PsiElement o2) {
|
||||
VirtualFile f1 = PsiUtilCore.getVirtualFile(o1);
|
||||
VirtualFile f2 = PsiUtilCore.getVirtualFile(o2);
|
||||
if (f1 == f2) return 0;
|
||||
if (f1 == null) return -1;
|
||||
if (f2 == null) return 1;
|
||||
return searchScope.compare(f2, f1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Collection<PsiClass> sortByClasspath(@NotNull List<PsiClass> classes, @NotNull GlobalSearchScope searchScope) {
|
||||
if (classes.size() > 1) {
|
||||
ContainerUtil.quickSort(classes, byClasspathComparator(searchScope));
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -421,7 +421,7 @@ public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostic
|
||||
@NotNull
|
||||
private static VirtualFile getRepresentativeVirtualFile(@NotNull Collection<JetFile> files) {
|
||||
JetFile firstFile = files.iterator().next();
|
||||
VirtualFile virtualFile = files.size() == 1 ? firstFile.getVirtualFile() : new LightVirtualFile();
|
||||
VirtualFile virtualFile = firstFile.getVirtualFile();
|
||||
assert virtualFile != null : "No virtual file for " + firstFile;
|
||||
return virtualFile;
|
||||
}
|
||||
|
||||
+4
-36
@@ -21,10 +21,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.libraries.LibraryUtil;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.ClassFileViewProvider;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsClassImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsFileImpl;
|
||||
@@ -71,12 +68,12 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
|
||||
private final Project project;
|
||||
|
||||
private final Comparator<JetFile> jetFileComparator;
|
||||
private final Comparator<PsiElement> scopeFileComparator;
|
||||
private final PsiManager psiManager;
|
||||
|
||||
public IDELightClassGenerationSupport(@NotNull Project project) {
|
||||
this.project = project;
|
||||
this.jetFileComparator = byScopeComparator(GlobalSearchScope.allScope(project));
|
||||
this.scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project));
|
||||
this.psiManager = PsiManager.getInstance(project);
|
||||
}
|
||||
|
||||
@@ -87,7 +84,7 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
assert !files.isEmpty() : "No files in package";
|
||||
|
||||
List<JetFile> sortedFiles = new ArrayList<JetFile>(files);
|
||||
Collections.sort(sortedFiles, jetFileComparator);
|
||||
Collections.sort(sortedFiles, scopeFileComparator);
|
||||
|
||||
JetFile file = sortedFiles.get(0);
|
||||
ResolveSessionForBodies session = KotlinCacheService.getInstance(file.getProject()).getLazyResolveSession(file);
|
||||
@@ -319,38 +316,9 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
for (Map.Entry<IdeaModuleInfo, List<JetFile>> entry : filesByInfo.entrySet()) {
|
||||
result.add(new KotlinLightPackageClassInfo(entry.getValue(), entry.getKey()));
|
||||
}
|
||||
sortByClasspath(wholeScope, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Comparator<JetFile> byScopeComparator(@NotNull final GlobalSearchScope searchScope) {
|
||||
return new Comparator<JetFile>() {
|
||||
@Override
|
||||
public int compare(@NotNull JetFile o1, @NotNull JetFile o2) {
|
||||
VirtualFile f1 = o1.getVirtualFile();
|
||||
VirtualFile f2 = o2.getVirtualFile();
|
||||
if (f1 == f2) return 0;
|
||||
if (f1 == null) return -1;
|
||||
if (f2 == null) return 1;
|
||||
return searchScope.compare(f1, f2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void sortByClasspath(@NotNull GlobalSearchScope wholeScope, @NotNull List<KotlinLightPackageClassInfo> result) {
|
||||
final Comparator<JetFile> byScopeComparator = byScopeComparator(wholeScope);
|
||||
Collections.sort(result, new Comparator<KotlinLightPackageClassInfo>() {
|
||||
@Override
|
||||
public int compare(@NotNull KotlinLightPackageClassInfo info1, @NotNull KotlinLightPackageClassInfo info2) {
|
||||
JetFile file1 = info1.getFiles().iterator().next();
|
||||
JetFile file2 = info2.getFiles().iterator().next();
|
||||
//classes earlier that would appear earlier on classpath should go first
|
||||
return -byScopeComparator.compare(file1, file2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static final class KotlinLightPackageClassInfo {
|
||||
private final Collection<JetFile> files;
|
||||
private final IdeaModuleInfo moduleInfo;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
package test1
|
||||
|
||||
class A
|
||||
@@ -0,0 +1,5 @@
|
||||
package test2
|
||||
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package test3
|
||||
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package test3
|
||||
|
||||
fun bar() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.asJava
|
||||
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.impl.ResolveScopeManager
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.KotlinLightClassForDecompiledDeclaration
|
||||
import org.jetbrains.kotlin.idea.test.JdkAndMockLibraryProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.idea.test.configureAs
|
||||
import java.io.File
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
class LightClassesClasspathSortingTest : KotlinCodeInsightTestCase() {
|
||||
fun testExplicitClass() {
|
||||
doTest("test1.A")
|
||||
}
|
||||
|
||||
fun testPackageClassOneFile() {
|
||||
doTest("test2.Test2Package")
|
||||
}
|
||||
|
||||
fun testPackageClassTwoFiles() {
|
||||
doTest("test3.Test3Package")
|
||||
}
|
||||
|
||||
private fun doTest(fqName: String) {
|
||||
// Same classes are in sources and in compiled Kotlin library. Test that light classes from sources have a priority.
|
||||
|
||||
// Configure library first to make classes be indexed before correspondent classes from sources
|
||||
val dirName = getTestName(true)
|
||||
getModule().configureAs(getProjectDescriptor(dirName))
|
||||
|
||||
val testDirRoot = File(getTestDataPath())
|
||||
val filePaths = File(testDirRoot, dirName).listFiles().map { it.relativeTo(testDirRoot) }.toArrayList().toTypedArray()
|
||||
configureByFiles(null, *filePaths)
|
||||
|
||||
checkLightClassBeforeDecompiled(fqName)
|
||||
}
|
||||
|
||||
private fun checkLightClassBeforeDecompiled(fqName: String) {
|
||||
val psiClass = JavaPsiFacade.getInstance(getProject()).findClass(fqName, ResolveScopeManager.getElementResolveScope(getFile()))
|
||||
|
||||
assertNotNull(psiClass, "Can't find class for $fqName")
|
||||
assert(psiClass is KotlinLightClassForExplicitDeclaration || psiClass is KotlinLightClassForPackage,
|
||||
"Should be an explicit light class, but was $fqName ${psiClass.javaClass}")
|
||||
assert(psiClass !is KotlinLightClassForDecompiledDeclaration,
|
||||
"Should not be decompiled light class: $fqName ${psiClass.javaClass}")
|
||||
}
|
||||
|
||||
private fun getProjectDescriptor(dir: String) =
|
||||
JdkAndMockLibraryProjectDescriptor(PluginTestCaseBase.getTestDataPathBase() + "/decompiler/lightClassesOrder/$dir", true)
|
||||
|
||||
override fun getTestDataPath(): String? {
|
||||
return PluginTestCaseBase.getTestDataPathBase() + "/decompiler/lightClassesOrder/"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user