Fix debugger tests.
- Index binaries by facade class fqName - Fix DebuggerUtils: should understand new facades - Refactor IDELightClassGenerationSupport - Add facadeSimpleName to KotlinFileStub
This commit is contained in:
committed by
Michael Bogdanov
parent
f9901f6075
commit
5ca8f7409a
+3
-1
@@ -59,7 +59,7 @@ import java.util.*
|
||||
getPackagePartFqName(facadeClassFqName.parent(), file.name)
|
||||
|
||||
public @jvmStatic fun getPackagePartFqName(packageFqName: FqName, fileName: String): FqName {
|
||||
val partClassName = getPartClassName(FileUtil.getNameWithoutExtension(fileName))
|
||||
val partClassName = getFilePartShortName(fileName)
|
||||
return packageFqName.child(Name.identifier(partClassName))
|
||||
}
|
||||
|
||||
@@ -91,4 +91,6 @@ import java.util.*
|
||||
public @jvmStatic fun getFilesForPart(partFqName: FqName, files: Collection<JetFile>): List<JetFile> =
|
||||
getFilesWithCallables(files).filter { getPackagePartFqName(it) == partFqName }
|
||||
|
||||
public @jvmStatic fun getFilePartShortName(fileName: String): String =
|
||||
getPartClassName(FileUtil.getNameWithoutExtension(fileName))
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
|
||||
public interface KotlinFileStub : PsiFileStub<JetFile> {
|
||||
public fun getPackageFqName(): FqName
|
||||
public fun getFacadeSimpleName(): String?
|
||||
public fun isScript(): Boolean
|
||||
public fun findImportsByAlias(alias: String): List<KotlinImportDirectiveStub>
|
||||
}
|
||||
|
||||
+3
-1
@@ -68,6 +68,7 @@ public class JetFileElementType extends IStubFileElementType<KotlinFileStub> {
|
||||
public void serialize(@NotNull KotlinFileStub stub, @NotNull StubOutputStream dataStream)
|
||||
throws IOException {
|
||||
dataStream.writeName(stub.getPackageFqName().asString());
|
||||
dataStream.writeName(stub.getFacadeSimpleName());
|
||||
dataStream.writeBoolean(stub.isScript());
|
||||
}
|
||||
|
||||
@@ -76,7 +77,8 @@ public class JetFileElementType extends IStubFileElementType<KotlinFileStub> {
|
||||
public KotlinFileStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
|
||||
StringRef packageFqNameAsString = dataStream.readName();
|
||||
boolean isScript = dataStream.readBoolean();
|
||||
return new KotlinFileStubImpl(null, packageFqNameAsString, isScript);
|
||||
StringRef facadeSimpleName = dataStream.readName();
|
||||
return new KotlinFileStubImpl(null, packageFqNameAsString, facadeSimpleName, isScript);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,14 +28,19 @@ import org.jetbrains.kotlin.psi.stubs.KotlinFileStub
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinImportDirectiveStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes
|
||||
|
||||
public class KotlinFileStubImpl(jetFile: JetFile?, private val packageName: StringRef, private val isScript: Boolean)// SCRIPT: PsiJetFileStubImpl knows about scripting
|
||||
: PsiFileStubImpl<JetFile>(jetFile), KotlinFileStub, PsiClassHolderFileStub<JetFile> {
|
||||
// SCRIPT: PsiJetFileStubImpl knows about scripting
|
||||
public class KotlinFileStubImpl(
|
||||
jetFile: JetFile?,
|
||||
private val packageName: StringRef,
|
||||
private val facadeShortName: StringRef?,
|
||||
private val isScript: Boolean
|
||||
) : PsiFileStubImpl<JetFile>(jetFile), KotlinFileStub, PsiClassHolderFileStub<JetFile> {
|
||||
|
||||
public constructor(jetFile: JetFile?, packageName: String, isScript: Boolean)
|
||||
: this(jetFile, StringRef.fromString(packageName)!!, isScript) {
|
||||
}
|
||||
: this(jetFile, StringRef.fromString(packageName)!!, null, isScript)
|
||||
|
||||
override fun getPackageFqName(): FqName = FqName(StringRef.toString(packageName)!!)
|
||||
override fun getFacadeSimpleName(): String? = StringRef.toString(facadeShortName)
|
||||
override fun isScript(): Boolean = isScript
|
||||
override fun getType(): IStubFileElementType<KotlinFileStub> = JetStubElementTypes.FILE
|
||||
|
||||
@@ -49,4 +54,18 @@ public class KotlinFileStubImpl(jetFile: JetFile?, private val packageName: Stri
|
||||
val importList = childrenStubs.firstOrNull { it.stubType == JetStubElementTypes.IMPORT_LIST } ?: return emptyList()
|
||||
return importList.childrenStubs.filterIsInstance<KotlinImportDirectiveStub>().filter { it.getAliasName() == alias }
|
||||
}
|
||||
|
||||
companion object {
|
||||
public fun forPackageStub(packageFqName: FqName, isScript: Boolean): KotlinFileStubImpl =
|
||||
KotlinFileStubImpl(null,
|
||||
StringRef.fromString(packageFqName.asString())!!,
|
||||
null,
|
||||
isScript)
|
||||
|
||||
public fun forFileFacadeStub(facadeFqName: FqName, isScript: Boolean): KotlinFileStubImpl =
|
||||
KotlinFileStubImpl(null,
|
||||
StringRef.fromString(facadeFqName.parent().asString())!!,
|
||||
StringRef.fromString(facadeFqName.shortName().asString())!!,
|
||||
isScript)
|
||||
}
|
||||
}
|
||||
|
||||
+62
-53
@@ -26,7 +26,6 @@ import com.intellij.psi.ClassFileViewProvider;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.PsiManagerImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsClassImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsFileImpl;
|
||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
|
||||
@@ -49,7 +48,6 @@ import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil;
|
||||
import org.jetbrains.kotlin.idea.stubindex.StaticFacadeIndexUtil;
|
||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
@@ -64,6 +62,7 @@ import java.util.*;
|
||||
|
||||
import static kotlin.KotlinPackage.*;
|
||||
import static org.jetbrains.kotlin.idea.stubindex.JetSourceFilterScope.kotlinSourceAndClassFiles;
|
||||
import static org.jetbrains.kotlin.idea.stubindex.JetSourceFilterScope.kotlinSourcesAndLibraries;
|
||||
|
||||
public class IDELightClassGenerationSupport extends LightClassGenerationSupport {
|
||||
|
||||
@@ -187,19 +186,6 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
return PackageIndexUtil.findFilesWithExactPackage(fqName, kotlinSourceAndClassFiles(searchScope, project), project);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Map<IdeaModuleInfo, List<JetFile>> groupByModuleInfo(@NotNull Collection<JetFile> allFiles) {
|
||||
return KotlinPackage.groupByTo(
|
||||
allFiles,
|
||||
new LinkedHashMap<IdeaModuleInfo, List<JetFile>>(),
|
||||
new Function1<JetFile, IdeaModuleInfo>() {
|
||||
@Override
|
||||
public IdeaModuleInfo invoke(JetFile file) {
|
||||
return ResolvePackage.getModuleInfo(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<JetClassOrObject> findClassOrObjectDeclarationsInPackage(
|
||||
@@ -294,27 +280,43 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
|
||||
IdeaModuleInfo moduleInfo = info.getModuleInfo();
|
||||
if (moduleInfo instanceof ModuleSourceInfo) {
|
||||
KotlinLightClassForFacade lightClass =
|
||||
KotlinLightClassForFacade.Factory.createForPackageFacade(psiManager, packageFqName, moduleInfo.contentScope(), files);
|
||||
if (lightClass == null) continue;
|
||||
|
||||
result.add(lightClass);
|
||||
|
||||
if (files.size() > 1) {
|
||||
for (JetFile file : files) {
|
||||
result.add(new FakeLightClassForFileOfPackage(psiManager, lightClass, file));
|
||||
}
|
||||
}
|
||||
result.addAll(getLightClassesForPackageFacadeWithSources(packageFqName, files, moduleInfo));
|
||||
}
|
||||
else {
|
||||
FqName packageFacadeFqName = PackageClassUtils.getPackageClassFqName(packageFqName);
|
||||
List<PsiClass> clsClasses = getLightClassesForDecompiledFacadeFiles(packageFacadeFqName, files);
|
||||
result.addAll(clsClasses);
|
||||
result.addAll(getLightClassesForDecompiledFacadeFiles(files));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<PsiClass> getLightClassesForPackageFacadeWithSources(
|
||||
@NotNull FqName packageFqName,
|
||||
@NotNull List<JetFile> facadeFiles,
|
||||
@NotNull IdeaModuleInfo moduleInfo
|
||||
) {
|
||||
KotlinLightClassForFacade lightClassForFacade =
|
||||
KotlinLightClassForFacade.Factory.createForPackageFacade(psiManager, packageFqName, moduleInfo.contentScope(), facadeFiles);
|
||||
return getLightClassesForFacadeWithFiles(lightClassForFacade, facadeFiles);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<PsiClass> getLightClassesForFacadeWithFiles(
|
||||
@Nullable KotlinLightClassForFacade lightClassForFacade,
|
||||
@NotNull List<JetFile> facadeFiles
|
||||
) {
|
||||
if (lightClassForFacade == null) return emptyList();
|
||||
|
||||
List<PsiClass> lightClasses = new ArrayList<PsiClass>();
|
||||
lightClasses.add(lightClassForFacade);
|
||||
if (facadeFiles.size() > 1) {
|
||||
for (JetFile file : facadeFiles) {
|
||||
lightClasses.add(new FakeLightClassForFileOfPackage(psiManager, lightClassForFacade, file));
|
||||
}
|
||||
}
|
||||
return lightClasses;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PsiClass> getFacadeClasses(@NotNull FqName facadeFqName, @NotNull GlobalSearchScope scope) {
|
||||
@@ -326,36 +328,48 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
|
||||
IdeaModuleInfo moduleInfo = info.getModuleInfo();
|
||||
if (moduleInfo instanceof ModuleSourceInfo) {
|
||||
KotlinLightClassForFacade lightClass =
|
||||
KotlinLightClassForFacade.Factory.createForFacade(psiManager, facadeFqName, moduleInfo.contentScope(), files);
|
||||
if (lightClass == null) continue;
|
||||
|
||||
result.add(lightClass);
|
||||
|
||||
if (files.size() > 1) {
|
||||
for (JetFile file : files) {
|
||||
result.add(new FakeLightClassForFileOfPackage(psiManager, lightClass, file));
|
||||
}
|
||||
}
|
||||
result.addAll(getLightClassesForStaticFacadeWithSources(facadeFqName, files, moduleInfo));
|
||||
}
|
||||
else {
|
||||
List<PsiClass> clsClasses = getLightClassesForDecompiledFacadeFiles(facadeFqName, files);
|
||||
result.addAll(clsClasses);
|
||||
result.addAll(getLightClassesForDecompiledFacadeFiles(files));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<PsiClass> getLightClassesForStaticFacadeWithSources(
|
||||
@NotNull FqName facadeFqName,
|
||||
@NotNull List<JetFile> facadeFiles,
|
||||
@NotNull IdeaModuleInfo moduleInfo
|
||||
) {
|
||||
KotlinLightClassForFacade lightClassForFacade = KotlinLightClassForFacade.Factory.createForFacade(
|
||||
psiManager, facadeFqName, moduleInfo.contentScope(), facadeFiles);
|
||||
return getLightClassesForFacadeWithFiles(lightClassForFacade, facadeFiles);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<JetFile> findFilesForFacade(@NotNull FqName facadeFqName, @NotNull GlobalSearchScope scope) {
|
||||
return StaticFacadeIndexUtil.findFilesForStaticFacade(facadeFqName, kotlinSourceAndClassFiles(scope, project), project);
|
||||
return StaticFacadeIndexUtil.findFilesForStaticFacade(facadeFqName, kotlinSourcesAndLibraries(scope, project), project);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<KotlinLightFacadeClassInfo> findFacadeClassesInfos(FqName facadeFqName, GlobalSearchScope scope) {
|
||||
Collection<JetFile> facadeFiles = findFilesForFacade(facadeFqName, scope);
|
||||
Map<IdeaModuleInfo, List<JetFile>> filesByInfo = groupByModuleInfo(facadeFiles);
|
||||
return groupFilesIntoFacadeLightClassesByModuleInfo(facadeFiles);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<KotlinLightFacadeClassInfo> groupFilesIntoFacadeLightClassesByModuleInfo(Collection<JetFile> facadeFiles) {
|
||||
Map<IdeaModuleInfo, List<JetFile>> filesByInfo = KotlinPackage.groupByTo(
|
||||
facadeFiles,
|
||||
new LinkedHashMap<IdeaModuleInfo, List<JetFile>>(),
|
||||
new Function1<JetFile, IdeaModuleInfo>() {
|
||||
@Override
|
||||
public IdeaModuleInfo invoke(JetFile file) {
|
||||
return ResolvePackage.getModuleInfo(file);
|
||||
}
|
||||
});
|
||||
List<KotlinLightFacadeClassInfo> result = new ArrayList<KotlinLightFacadeClassInfo>();
|
||||
for (Map.Entry<IdeaModuleInfo, List<JetFile>> entry : filesByInfo.entrySet()) {
|
||||
result.add(new KotlinLightFacadeClassInfo(entry.getValue(), entry.getKey()));
|
||||
@@ -374,8 +388,8 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static List<PsiClass> getLightClassesForDecompiledFacadeFiles(@NotNull FqName facadeFqName, @NotNull List<JetFile> filesWithCallables) {
|
||||
@NotNull
|
||||
private static List<PsiClass> getLightClassesForDecompiledFacadeFiles(@NotNull List<JetFile> filesWithCallables) {
|
||||
List<PsiClass> lightClasses = new ArrayList<PsiClass>();
|
||||
for (JetFile file : filesWithCallables) {
|
||||
if (file.isCompiled()) {
|
||||
@@ -390,12 +404,7 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
@NotNull FqName fqName, @NotNull GlobalSearchScope wholeScope
|
||||
) {
|
||||
Collection<JetFile> allFiles = findFilesForPackage(fqName, wholeScope);
|
||||
Map<IdeaModuleInfo, List<JetFile>> filesByInfo = groupByModuleInfo(allFiles);
|
||||
List<KotlinLightFacadeClassInfo> result = new ArrayList<KotlinLightFacadeClassInfo>();
|
||||
for (Map.Entry<IdeaModuleInfo, List<JetFile>> entry : filesByInfo.entrySet()) {
|
||||
result.add(new KotlinLightFacadeClassInfo(entry.getValue(), entry.getKey()));
|
||||
}
|
||||
return result;
|
||||
return groupFilesIntoFacadeLightClassesByModuleInfo(allFiles);
|
||||
}
|
||||
|
||||
private static final class KotlinLightFacadeClassInfo {
|
||||
@@ -445,7 +454,7 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
return null;
|
||||
}
|
||||
PsiManager manager = PsiManager.getInstance(decompiledKotlinFile.getProject());
|
||||
ClsFileImpl fakeFile = new ClsFileImpl((PsiManagerImpl) manager, new ClassFileViewProvider(manager, virtualFile)) {
|
||||
ClsFileImpl fakeFile = new ClsFileImpl(new ClassFileViewProvider(manager, virtualFile)) {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
|
||||
+2
-2
@@ -68,7 +68,7 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() {
|
||||
header.isCompatiblePackageFacadeKind() -> {
|
||||
val packageData = JvmProtoBufUtil.readPackageDataFrom(annotationData)
|
||||
val context = components.createContext(packageData.getNameResolver(), packageFqName)
|
||||
createPackageFacadeFileStub(packageData.getPackageProto(), packageFqName, context)
|
||||
createPackageFacadeStub(packageData.getPackageProto(), packageFqName, context)
|
||||
}
|
||||
header.isCompatibleClassKind() -> {
|
||||
if (header.classKind != JvmAnnotationNames.KotlinClass.Kind.CLASS) return null
|
||||
@@ -79,7 +79,7 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() {
|
||||
header.isCompatibleFileFacadeKind() -> {
|
||||
val packageData = JvmProtoBufUtil.readPackageDataFrom(annotationData)
|
||||
val context = components.createContext(packageData.getNameResolver(), packageFqName)
|
||||
createPackageFacadeFileStub(packageData.getPackageProto(), packageFqName, context)
|
||||
createFileFacadeStub(packageData.getPackageProto(), classId.asSingleFqName(), context)
|
||||
}
|
||||
else -> throw IllegalStateException("Should have processed " + file.getPath() + " with header $header")
|
||||
}
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ public open class KotlinJavaScriptStubBuilder : ClsStubBuilder() {
|
||||
if (isPackageHeader) {
|
||||
val packageData = content.toPackageData(nameResolver)
|
||||
val context = components.createContext(packageData.getNameResolver(), packageFqName)
|
||||
return createPackageFacadeFileStub(packageData.getPackageProto(), packageFqName, context)
|
||||
return createPackageFacadeStub(packageData.getPackageProto(), packageFqName, context)
|
||||
}
|
||||
else {
|
||||
val classData = content.toClassData(nameResolver)
|
||||
|
||||
+24
-4
@@ -42,12 +42,13 @@ fun createTopLevelClassStub(classId: ClassId, classProto: ProtoBuf.Class, contex
|
||||
return fileStub
|
||||
}
|
||||
|
||||
fun createPackageFacadeFileStub(
|
||||
fun createPackageFacadeStub(
|
||||
packageProto: ProtoBuf.Package,
|
||||
packageFqName: FqName,
|
||||
c: ClsStubBuilderContext
|
||||
): KotlinFileStubImpl {
|
||||
val fileStub = createFileStub(packageFqName)
|
||||
val fileStub = KotlinFileStubImpl.forPackageStub(packageFqName, packageFqName.isRoot)
|
||||
setupFileStub(fileStub, packageFqName)
|
||||
val container = ProtoContainer(null, packageFqName)
|
||||
for (callableProto in packageProto.getMemberList()) {
|
||||
createCallableStub(fileStub, callableProto, c, container)
|
||||
@@ -55,14 +56,33 @@ fun createPackageFacadeFileStub(
|
||||
return fileStub
|
||||
}
|
||||
|
||||
fun createFileFacadeStub(
|
||||
packageProto: ProtoBuf.Package,
|
||||
facadeFqName: FqName,
|
||||
c: ClsStubBuilderContext
|
||||
): KotlinFileStubImpl {
|
||||
val packageFqName = facadeFqName.parent()
|
||||
val fileStub = KotlinFileStubImpl.forFileFacadeStub(facadeFqName, packageFqName.isRoot)
|
||||
setupFileStub(fileStub, packageFqName)
|
||||
val container = ProtoContainer(null, facadeFqName.parent())
|
||||
for (callableProto in packageProto.getMemberList()) {
|
||||
createCallableStub(fileStub, callableProto, c, container)
|
||||
}
|
||||
return fileStub
|
||||
}
|
||||
|
||||
fun createIncompatibleAbiVersionFileStub() = createFileStub(FqName.ROOT)
|
||||
|
||||
fun createFileStub(packageFqName: FqName): KotlinFileStubImpl {
|
||||
val fileStub = KotlinFileStubImpl(null, packageFqName.asString(), packageFqName.isRoot())
|
||||
val fileStub = KotlinFileStubImpl.forPackageStub(packageFqName, packageFqName.isRoot)
|
||||
setupFileStub(fileStub, packageFqName)
|
||||
return fileStub
|
||||
}
|
||||
|
||||
private fun setupFileStub(fileStub: KotlinFileStubImpl, packageFqName: FqName) {
|
||||
val packageDirectiveStub = KotlinPlaceHolderStubImpl<JetPackageDirective>(fileStub, JetStubElementTypes.PACKAGE_DIRECTIVE)
|
||||
createStubForPackageName(packageDirectiveStub, packageFqName)
|
||||
KotlinPlaceHolderStubImpl<JetImportList>(fileStub, JetStubElementTypes.IMPORT_LIST)
|
||||
return fileStub
|
||||
}
|
||||
|
||||
fun createStubForPackageName(packageDirectiveStub: KotlinPlaceHolderStubImpl<JetPackageDirective>, packageFqName: FqName) {
|
||||
|
||||
+2
-2
@@ -29,10 +29,10 @@ public class JetStaticFacadeClassIndex private constructor() : StringStubIndexEx
|
||||
super.get(key, project, JetSourceFilterScope.kotlinSourcesAndLibraries(scope, project))
|
||||
|
||||
companion object {
|
||||
private val KEY = KotlinIndexUtil.createIndexKey(javaClass<JetStaticFacadeClassIndex>())
|
||||
private val KEY = KotlinIndexUtil.createIndexKey(JetStaticFacadeClassIndex::class.java)
|
||||
|
||||
public val INSTANCE: JetStaticFacadeClassIndex = JetStaticFacadeClassIndex()
|
||||
|
||||
public fun getInstance(): JetStaticFacadeClassIndex = INSTANCE
|
||||
public @jvmStatic fun getInstance(): JetStaticFacadeClassIndex = INSTANCE
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -18,17 +18,26 @@ package org.jetbrains.kotlin.idea.stubindex
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import kotlin.platform.platformStatic
|
||||
|
||||
public object StaticFacadeIndexUtil {
|
||||
|
||||
platformStatic public fun findFilesForStaticFacade(
|
||||
@jvmStatic public fun findFilesForStaticFacade(
|
||||
facadeFqName: FqName,
|
||||
searchScope: GlobalSearchScope,
|
||||
project: Project
|
||||
) : Collection<JetFile> =
|
||||
JetStaticFacadeClassIndex.INSTANCE.get(facadeFqName.asString(), project, searchScope)
|
||||
|
||||
// TODO change as we introduce multi-file facades (this will require a separate index)
|
||||
@jvmStatic public fun findFilesForFilePart(
|
||||
partFqName: FqName,
|
||||
searchScope: GlobalSearchScope,
|
||||
project: Project
|
||||
) : Collection<JetFile> =
|
||||
PackagePartClassUtils.getFilesWithCallables(
|
||||
JetStaticFacadeClassIndex.INSTANCE.get(partFqName.asString(), project, searchScope))
|
||||
}
|
||||
+11
-3
@@ -20,6 +20,7 @@ import com.intellij.psi.stubs.IndexSink;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.JetClassOrObject;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
import org.jetbrains.kotlin.psi.stubs.*;
|
||||
@@ -36,11 +37,18 @@ public class StubIndexServiceImpl implements StubIndexService {
|
||||
|
||||
sink.occurrence(JetExactPackagesIndex.getInstance().getKey(), packageFqName.asString());
|
||||
|
||||
JetFile psi = stub.getPsi();
|
||||
if (psi != null) {
|
||||
FqName staticFacadeFqName = PackagePartClassUtils.getPackagePartFqName(psi);
|
||||
String facadeSimpleName = stub.getFacadeSimpleName();
|
||||
if (facadeSimpleName != null) {
|
||||
FqName staticFacadeFqName = packageFqName.child(Name.identifier(facadeSimpleName));
|
||||
sink.occurrence(JetStaticFacadeClassIndex.INSTANCE.getKey(), staticFacadeFqName.asString());
|
||||
}
|
||||
else {
|
||||
JetFile psi = stub.getPsi();
|
||||
if (psi != null) {
|
||||
FqName staticFacadeFqName = PackagePartClassUtils.getPackagePartFqName(psi);
|
||||
sink.occurrence(JetStaticFacadeClassIndex.INSTANCE.getKey(), staticFacadeFqName.asString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,8 +28,6 @@ import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.util.DebuggerUtils;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||
|
||||
@@ -53,38 +51,25 @@ public class JetExceptionFilter implements Filter {
|
||||
StackTraceElement element = parseStackTraceLine(line);
|
||||
if (element == null) return null;
|
||||
|
||||
// All true classes should be handled correctly in the default ExceptionFilter. Special cases:
|
||||
// - static facades;
|
||||
// - package facades / package parts (generated by pre-M13 compiled);
|
||||
// - local classes (and closures) in top-level function and property declarations.
|
||||
String fileName = element.getFileName();
|
||||
|
||||
// fullyQualifiedName is of format "package.Class$Inner"
|
||||
String fullyQualifiedName = element.getClassName();
|
||||
|
||||
// All classes except package classes, package parts and top level closures are handled correctly in the default ExceptionFilter
|
||||
if (!isPackageClassOrPackagePartPrefixedName(fullyQualifiedName)) return null;
|
||||
int lineNumber = element.getLineNumber() - 1;
|
||||
|
||||
String internalName = fullyQualifiedName.replace('.', '/');
|
||||
JvmClassName jvmClassName = JvmClassName.byInternalName(internalName);
|
||||
|
||||
JetFile file = DebuggerUtils.findSourceFileForClass(project, searchScope, jvmClassName, fileName, element.getLineNumber() - 1);
|
||||
JetFile file = DebuggerUtils.findSourceFileForClass(project, searchScope, jvmClassName, fileName, lineNumber);
|
||||
|
||||
if (file == null) return null;
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (virtualFile == null) return null;
|
||||
|
||||
return new OpenFileHyperlinkInfo(project, virtualFile, element.getLineNumber() - 1);
|
||||
}
|
||||
|
||||
private static boolean isPackageClassOrPackagePartPrefixedName(String fqName) {
|
||||
if (fqName.equals(PackageClassUtils.getPackageClassName(FqName.ROOT))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int lastDot = fqName.lastIndexOf('.');
|
||||
String classNameWithInners = fqName.substring(lastDot + 1);
|
||||
int firstDollar = classNameWithInners.indexOf('$');
|
||||
String className = firstDollar >= 0 ? classNameWithInners.substring(0, firstDollar) : classNameWithInners;
|
||||
|
||||
String packageClassName = PackageClassUtils.getPackageClassName(new FqName(fqName).parent());
|
||||
return packageClassName.equals(className);
|
||||
return new OpenFileHyperlinkInfo(project, virtualFile, lineNumber);
|
||||
}
|
||||
|
||||
// Matches strings like "\tat test.TestPackage$foo$f$1.invoke(a.kt:3)\n"
|
||||
|
||||
@@ -19,8 +19,10 @@ package org.jetbrains.kotlin.idea.util;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.libraries.LibraryUtil;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -32,13 +34,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade;
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils;
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde;
|
||||
import org.jetbrains.kotlin.idea.debugger.DebuggerPackage;
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolvePackage;
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade;
|
||||
import org.jetbrains.kotlin.idea.stubindex.StaticFacadeIndexUtil;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.CompositeBindingContext;
|
||||
@@ -56,6 +59,8 @@ public class DebuggerUtils {
|
||||
private DebuggerUtils() {
|
||||
}
|
||||
|
||||
private static final Set<String> KOTLIN_EXTENSIONS = Sets.newHashSet("kt", "kts");
|
||||
|
||||
@Nullable
|
||||
public static JetFile findSourceFileForClass(
|
||||
@NotNull Project project,
|
||||
@@ -64,6 +69,9 @@ public class DebuggerUtils {
|
||||
@NotNull final String fileName,
|
||||
final int lineNumber
|
||||
) {
|
||||
String extension = FileUtilRt.getExtension(fileName);
|
||||
if (!KOTLIN_EXTENSIONS.contains(extension)) return null;
|
||||
|
||||
Collection<JetFile> filesInPackage = findFilesWithExactPackage(className.getPackageFqName(), searchScope, project);
|
||||
Collection<JetFile> filesWithExactName = Collections2.filter(filesInPackage, new Predicate<JetFile>() {
|
||||
@Override
|
||||
@@ -78,6 +86,19 @@ public class DebuggerUtils {
|
||||
return filesWithExactName.iterator().next();
|
||||
}
|
||||
|
||||
// Static facade or inner class of such facade?
|
||||
FqName partFqName = className.getFqNameForClassNameWithoutDollars();
|
||||
Collection<JetFile> filesForPart = StaticFacadeIndexUtil.findFilesForFilePart(partFqName, searchScope, project);
|
||||
if (!filesForPart.isEmpty()) {
|
||||
for (JetFile file : filesForPart) {
|
||||
if (file.getName().equals(fileName)) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
// Do not fall back to decompiled files (which have different name).
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isPackageClassName(className)) {
|
||||
for (JetFile file : filesWithExactName) {
|
||||
boolean hasTopLevelMembers = KotlinPackage.any(file.getDeclarations(), new Function1<JetDeclaration, Boolean>() {
|
||||
@@ -108,10 +129,11 @@ public class DebuggerUtils {
|
||||
@Override
|
||||
public Boolean invoke(JetFile file) {
|
||||
Integer startLineOffset = CodeInsightUtils.getStartLineOffset(file, lineNumber);
|
||||
assert startLineOffset != null : "Cannot find start line offset for file " + file.getName() + ", line " + lineNumber;
|
||||
assert startLineOffset != null : "Cannot find start line offset for file " + file.getName() + ", line " +
|
||||
lineNumber;
|
||||
JetDeclaration elementAt = PsiTreeUtil.getParentOfType(file.findElementAt(startLineOffset), JetDeclaration.class);
|
||||
return elementAt != null &&
|
||||
className.getInternalName().equals(DebuggerPackage.findPackagePartInternalNameForLibraryFile(elementAt));
|
||||
className.getInternalName().equals(DebuggerPackage.findPackagePartInternalNameForLibraryFile(elementAt));
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
class A {
|
||||
fun foo() {
|
||||
println("Hello!")
|
||||
}
|
||||
}
|
||||
@@ -129,6 +129,11 @@ public class JetExceptionFilterTest : MultiFileTestCase() {
|
||||
doTest("2/foo2.kt", 4, { file -> "" + PackagePartClassUtils.getDefaultPartFqName(packageClassFqName, file) + "\$foo\$f\$1" })
|
||||
}
|
||||
|
||||
public fun testKotlinClass() {
|
||||
val kotlinClassFqName = "A"
|
||||
doTest("a.kt", 3, { kotlinClassFqName })
|
||||
}
|
||||
|
||||
public fun testLibrarySources() {
|
||||
val mockLibrary = MockLibraryUtil.compileLibraryToJar(getTestDataPath() + getTestRoot() + "mockLibrary", "mockLibrary", true)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user