From d1d18618b543562085b2181c72d612dbbcd49ab6 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Mon, 7 Sep 2015 15:14:09 +0300 Subject: [PATCH] J2K IDELightClassGenerationSupport: autoconvert --- .../resolve/IDELightClassGenerationSupport.kt | 740 ++++++++---------- 1 file changed, 322 insertions(+), 418 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt index 7a5c3e5eab2..1d63c8956af 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt @@ -14,514 +14,418 @@ * limitations under the License. */ -package org.jetbrains.kotlin.idea.caches.resolve; +package org.jetbrains.kotlin.idea.caches.resolve -import com.intellij.ide.highlighter.JavaClassFileType; -import com.intellij.openapi.diagnostic.Logger; -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.impl.compiled.ClsClassImpl; -import com.intellij.psi.impl.compiled.ClsFileImpl; -import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; -import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.stubs.PsiClassHolderFileStub; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.cls.ClsFormatException; -import kotlin.KotlinPackage; -import kotlin.jvm.functions.Function1; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.asJava.*; -import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.idea.decompiler.navigation.JetSourceNavigationHelper; -import org.jetbrains.kotlin.idea.resolve.ResolutionFacade; -import org.jetbrains.kotlin.idea.stubindex.JetFullClassNameIndex; -import org.jetbrains.kotlin.idea.stubindex.JetTopLevelClassByPackageIndex; -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.PackagePartClassUtils; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.name.Name; -import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage; -import org.jetbrains.kotlin.resolve.BindingContext; -import org.jetbrains.kotlin.resolve.lazy.*; -import org.jetbrains.kotlin.resolve.scopes.JetScope; +import com.intellij.ide.highlighter.JavaClassFileType +import com.intellij.openapi.diagnostic.Logger +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.impl.compiled.ClsClassImpl +import com.intellij.psi.impl.compiled.ClsFileImpl +import com.intellij.psi.impl.java.stubs.PsiJavaFileStub +import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.stubs.PsiClassHolderFileStub +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.util.cls.ClsFormatException +import kotlin.KotlinPackage +import org.jetbrains.kotlin.asJava.* +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.idea.decompiler.navigation.JetSourceNavigationHelper +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.idea.stubindex.JetFullClassNameIndex +import org.jetbrains.kotlin.idea.stubindex.JetTopLevelClassByPackageIndex +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.PackagePartClassUtils +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.lazy.* +import org.jetbrains.kotlin.resolve.scopes.JetScope -import java.io.IOException; -import java.util.*; +import java.io.IOException +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; +import kotlin.KotlinPackage.* +import org.jetbrains.kotlin.idea.stubindex.JetSourceFilterScope.kotlinSourceAndClassFiles +import org.jetbrains.kotlin.idea.stubindex.JetSourceFilterScope.kotlinSourcesAndLibraries -public class IDELightClassGenerationSupport extends LightClassGenerationSupport { +public class IDELightClassGenerationSupport(private val project: Project) : LightClassGenerationSupport() { - private static final Logger LOG = Logger.getInstance(IDELightClassGenerationSupport.class); + private val scopeFileComparator: Comparator + private val psiManager: PsiManager - private final Project project; - - private final Comparator scopeFileComparator; - private final PsiManager psiManager; - - public IDELightClassGenerationSupport(@NotNull Project project) { - this.project = project; - this.scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project)); - this.psiManager = PsiManager.getInstance(project); + init { + this.scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project)) + this.psiManager = PsiManager.getInstance(project) } - @NotNull - @Override - public LightClassConstructionContext getContextForPackage(@NotNull Collection files) { - assert !files.isEmpty() : "No files in package"; + override fun getContextForPackage(files: Collection): LightClassConstructionContext { + assert(!files.isEmpty(), "No files in package") - return getContextForFiles(files); + return getContextForFiles(files) } - @NotNull - private LightClassConstructionContext getContextForFiles(@NotNull Collection files) { - List sortedFiles = new ArrayList(files); - Collections.sort(sortedFiles, scopeFileComparator); + private fun getContextForFiles(files: Collection): LightClassConstructionContext { + val sortedFiles = ArrayList(files) + Collections.sort(sortedFiles, scopeFileComparator) - JetFile file = sortedFiles.get(0); - ResolveSession resolveSession = ResolvePackage.getResolutionFacade(file).getFrontendService(ResolveSession.class); - forceResolvePackageDeclarations(files, resolveSession); - return new LightClassConstructionContext(resolveSession.getBindingContext(), resolveSession.getModuleDescriptor()); + val file = sortedFiles.get(0) + val resolveSession = file.getResolutionFacade().getFrontendService(javaClass()) + forceResolvePackageDeclarations(files, resolveSession) + return LightClassConstructionContext(resolveSession.bindingContext, resolveSession.getModuleDescriptor()) } - @NotNull - @Override - public LightClassConstructionContext getContextForClassOrObject(@NotNull JetClassOrObject classOrObject) { - ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(classOrObject); + override fun getContextForClassOrObject(classOrObject: JetClassOrObject): LightClassConstructionContext { + val resolutionFacade = classOrObject.getResolutionFacade() - ModuleDescriptor moduleDescriptor = resolutionFacade.getModuleDescriptor(); - BindingContext bindingContext = resolutionFacade.analyze(classOrObject, BodyResolveMode.FULL); + val moduleDescriptor = resolutionFacade.moduleDescriptor + val bindingContext = resolutionFacade.analyze(classOrObject, BodyResolveMode.FULL) if (classOrObject.isLocal()) { - ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, classOrObject); + val descriptor = bindingContext.get(BindingContext.CLASS, classOrObject) if (descriptor == null) { - LOG.warn("No class descriptor in context for class: " + PsiUtilPackage.getElementTextWithContext(classOrObject)); - return new LightClassConstructionContext(bindingContext, moduleDescriptor); + LOG.warn("No class descriptor in context for class: " + classOrObject.getElementTextWithContext()) + return LightClassConstructionContext(bindingContext, moduleDescriptor) } - ForceResolveUtil.forceResolveAllContents(descriptor); + ForceResolveUtil.forceResolveAllContents(descriptor) - return new LightClassConstructionContext(bindingContext, moduleDescriptor); + return LightClassConstructionContext(bindingContext, moduleDescriptor) } - ForceResolveUtil.forceResolveAllContents(resolutionFacade.resolveToDescriptor(classOrObject)); - return new LightClassConstructionContext(bindingContext, moduleDescriptor); + ForceResolveUtil.forceResolveAllContents(resolutionFacade.resolveToDescriptor(classOrObject)) + return LightClassConstructionContext(bindingContext, moduleDescriptor) } - @NotNull - @Override - public LightClassConstructionContext getContextForFacade(@NotNull Collection files) { - assert !files.isEmpty() : "No files in facade"; + override fun getContextForFacade(files: Collection): LightClassConstructionContext { + assert(!files.isEmpty(), "No files in facade") - return getContextForFiles(files); + return getContextForFiles(files) } - private static void forceResolvePackageDeclarations(@NotNull Collection files, @NotNull KotlinCodeAnalyzer session) { - for (JetFile file : files) { - // SCRIPT: not supported - if (file.isScript()) continue; - - FqName packageFqName = file.getPackageFqName(); - - // make sure we create a package descriptor - PackageViewDescriptor packageDescriptor = session.getModuleDescriptor().getPackage(packageFqName); - if (packageDescriptor.isEmpty()) { - LOG.warn("No descriptor found for package " + packageFqName + " in file " + file.getName() + "\n" + file.getText()); - session.forceResolveAll(); - continue; - } - - for (JetDeclaration declaration : file.getDeclarations()) { - if (declaration instanceof JetFunction) { - JetFunction jetFunction = (JetFunction) declaration; - Name name = jetFunction.getNameAsSafeName(); - Collection functions = packageDescriptor.getMemberScope().getFunctions(name, NoLookupLocation.FROM_IDE); - for (FunctionDescriptor descriptor : functions) { - ForceResolveUtil.forceResolveAllContents(descriptor); - } - } - else if (declaration instanceof JetProperty) { - JetProperty jetProperty = (JetProperty) declaration; - Name name = jetProperty.getNameAsSafeName(); - Collection properties = packageDescriptor.getMemberScope().getProperties(name, NoLookupLocation.FROM_IDE); - for (VariableDescriptor descriptor : properties) { - ForceResolveUtil.forceResolveAllContents(descriptor); - } - } - else if (declaration instanceof JetClassOrObject) { - // Do nothing: we are not interested in classes - } - else { - LOG.error("Unsupported declaration kind: " + declaration + " in file " + file.getName() + "\n" + file.getText()); - } - } - } + override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection { + return JetFullClassNameIndex.getInstance().get(fqName.asString(), project, kotlinSourceAndClassFiles(searchScope, project)) } - @NotNull - @Override - public Collection findClassOrObjectDeclarations(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope) { - return JetFullClassNameIndex.getInstance().get(fqName.asString(), project, kotlinSourceAndClassFiles(searchScope, project)); + override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection { + return PackageIndexUtil.findFilesWithExactPackage(fqName, kotlinSourceAndClassFiles(searchScope, project), project) } - @NotNull - @Override - public Collection findFilesForPackage(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope) { - return PackageIndexUtil.findFilesWithExactPackage(fqName, kotlinSourceAndClassFiles(searchScope, project), project); - } - - @NotNull - @Override - public Collection findClassOrObjectDeclarationsInPackage( - @NotNull FqName packageFqName, @NotNull GlobalSearchScope searchScope - ) { + override fun findClassOrObjectDeclarationsInPackage( + packageFqName: FqName, searchScope: GlobalSearchScope): Collection { return JetTopLevelClassByPackageIndex.getInstance().get( - packageFqName.asString(), project, kotlinSourceAndClassFiles(searchScope, project) - ); + packageFqName.asString(), project, kotlinSourceAndClassFiles(searchScope, project)) } - @Override - public boolean packageExists(@NotNull FqName fqName, @NotNull GlobalSearchScope scope) { - return PackageIndexUtil.packageExists(fqName, kotlinSourceAndClassFiles(scope, project), project); + override fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean { + return PackageIndexUtil.packageExists(fqName, kotlinSourceAndClassFiles(scope, project), project) } - @NotNull - @Override - public Collection getSubPackages(@NotNull FqName fqn, @NotNull GlobalSearchScope scope) { - return PackageIndexUtil.getSubPackageFqNames(fqn, kotlinSourceAndClassFiles(scope, project), project, JetScope.ALL_NAME_FILTER); + override fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection { + return PackageIndexUtil.getSubPackageFqNames(fqn, kotlinSourceAndClassFiles(scope, project), project, JetScope.ALL_NAME_FILTER) } - @Nullable - @Override - public PsiClass getPsiClass(@NotNull JetClassOrObject classOrObject) { - VirtualFile virtualFile = classOrObject.getContainingFile().getVirtualFile(); - if (virtualFile != null && LibraryUtil.findLibraryEntry(virtualFile, classOrObject.getProject()) != null) { + override fun getPsiClass(classOrObject: JetClassOrObject): PsiClass? { + val virtualFile = classOrObject.containingFile.virtualFile + if (virtualFile != null && LibraryUtil.findLibraryEntry(virtualFile, classOrObject.project) != null) { if (ProjectRootsUtil.isLibraryClassFile(project, virtualFile)) { - return getLightClassForDecompiledClassOrObject(classOrObject); + return getLightClassForDecompiledClassOrObject(classOrObject) } - return JetSourceNavigationHelper.getOriginalClass(classOrObject); + return JetSourceNavigationHelper.getOriginalClass(classOrObject) } - return KotlinLightClassForExplicitDeclaration.Companion.create(psiManager, classOrObject); + return KotlinLightClassForExplicitDeclaration.create(psiManager, classOrObject) } - @Nullable - private static PsiClass getLightClassForDecompiledClassOrObject(@NotNull JetClassOrObject decompiledClassOrObject) { - if (decompiledClassOrObject instanceof JetEnumEntry) { - return null; - } - JetFile containingJetFile = decompiledClassOrObject.getContainingJetFile(); - if (!containingJetFile.isCompiled()) { - return null; - } - PsiClass rootLightClassForDecompiledFile = createLightClassForDecompiledKotlinFile(containingJetFile); - if (rootLightClassForDecompiledFile == null) return null; + override fun getPackageClasses(packageFqName: FqName, scope: GlobalSearchScope): Collection { + val result = ArrayList() + val packageClassesInfos = findPackageClassesInfos(packageFqName, scope) + for (info in packageClassesInfos) { + val files = PackagePartClassUtils.getFilesWithCallables(info.files) + if (files.isEmpty()) continue - return findCorrespondingLightClass(decompiledClassOrObject, rootLightClassForDecompiledFile); - } - - @NotNull - private static PsiClass findCorrespondingLightClass( - @NotNull JetClassOrObject decompiledClassOrObject, - @NotNull PsiClass rootLightClassForDecompiledFile - ) { - FqName relativeFqName = getClassRelativeName(decompiledClassOrObject); - Iterator iterator = relativeFqName.pathSegments().iterator(); - Name base = iterator.next(); - assert rootLightClassForDecompiledFile.getName().equals(base.asString()) - : "Light class for file:\n" + decompiledClassOrObject.getContainingJetFile().getVirtualFile().getCanonicalPath() - + "\nwas expected to have name: " + base.asString() + "\n Actual: " + rootLightClassForDecompiledFile.getName(); - PsiClass current = rootLightClassForDecompiledFile; - while (iterator.hasNext()) { - Name name = iterator.next(); - PsiClass innerClass = current.findInnerClassByName(name.asString(), false); - assert innerClass != null : "Could not find corresponding inner/nested class " + relativeFqName + " in class " + decompiledClassOrObject.getFqName() + "\n" + - "File: " + decompiledClassOrObject.getContainingJetFile().getVirtualFile().getName(); - current = innerClass; - } - return current; - } - - @NotNull - private static FqName getClassRelativeName(@NotNull JetClassOrObject decompiledClassOrObject) { - Name name = decompiledClassOrObject.getNameAsName(); - assert name != null; - JetClassOrObject parent = PsiTreeUtil.getParentOfType(decompiledClassOrObject, JetClassOrObject.class, true); - if (parent == null) { - assert decompiledClassOrObject.isTopLevel(); - return FqName.topLevel(name); - } - return getClassRelativeName(parent).child(name); - } - - @NotNull - @Override - public Collection getPackageClasses(@NotNull FqName packageFqName, @NotNull GlobalSearchScope scope) { - List result = new ArrayList(); - List packageClassesInfos = findPackageClassesInfos(packageFqName, scope); - for (KotlinLightFacadeClassInfo info : packageClassesInfos) { - List files = PackagePartClassUtils.getFilesWithCallables(info.getFiles()); - if (files.isEmpty()) continue; - - IdeaModuleInfo moduleInfo = info.getModuleInfo(); - if (moduleInfo instanceof ModuleSourceInfo) { - result.addAll(getLightClassesForPackageFacadeWithSources(packageFqName, files, moduleInfo)); + val moduleInfo = info.moduleInfo + if (moduleInfo is ModuleSourceInfo) { + result.addAll(getLightClassesForPackageFacadeWithSources(packageFqName, files, moduleInfo)) } else { - result.addAll(getLightClassesForDecompiledFacadeFiles(files)); + result.addAll(getLightClassesForDecompiledFacadeFiles(files)) } } - return result; + return result } - @NotNull - private List getLightClassesForPackageFacadeWithSources( - @NotNull FqName packageFqName, - @NotNull List facadeFiles, - @NotNull IdeaModuleInfo moduleInfo - ) { - KotlinLightClassForFacade lightClassForFacade = - KotlinLightClassForFacade.Factory.createForPackageFacade(psiManager, packageFqName, moduleInfo.contentScope(), facadeFiles); - return getLightClassesForFacadeWithFiles(lightClassForFacade, facadeFiles); + private fun getLightClassesForPackageFacadeWithSources( + packageFqName: FqName, + facadeFiles: List, + moduleInfo: IdeaModuleInfo): List { + val lightClassForFacade = KotlinLightClassForFacade.createForPackageFacade(psiManager, packageFqName, moduleInfo.contentScope(), facadeFiles) + return getLightClassesForFacadeWithFiles(lightClassForFacade, facadeFiles) } - @NotNull - private List getLightClassesForFacadeWithFiles( - @Nullable KotlinLightClassForFacade lightClassForFacade, - @NotNull List facadeFiles - ) { - if (lightClassForFacade == null) return emptyList(); + private fun getLightClassesForFacadeWithFiles( + lightClassForFacade: KotlinLightClassForFacade?, + facadeFiles: List): List { + if (lightClassForFacade == null) return emptyList() - List lightClasses = new ArrayList(); - lightClasses.add(lightClassForFacade); + val lightClasses = ArrayList() + lightClasses.add(lightClassForFacade) if (facadeFiles.size() > 1) { - for (JetFile file : facadeFiles) { - lightClasses.add(new FakeLightClassForFileOfPackage(psiManager, lightClassForFacade, file)); + for (file in facadeFiles) { + lightClasses.add(FakeLightClassForFileOfPackage(psiManager, lightClassForFacade, file)) } } - return lightClasses; + return lightClasses } - @NotNull - @Override - public Collection getFacadeClasses(@NotNull FqName facadeFqName, @NotNull GlobalSearchScope scope) { - List result = new ArrayList(); - List facadeClassesInfos = findFacadeClassesInfos(facadeFqName, scope); - for (KotlinLightFacadeClassInfo info : facadeClassesInfos) { - List files = PackagePartClassUtils.getFilesWithCallables(info.getFiles()); - if (files.isEmpty()) continue; + override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection { + val result = ArrayList() + val facadeClassesInfos = findFacadeClassesInfos(facadeFqName, scope) + for (info in facadeClassesInfos) { + val files = PackagePartClassUtils.getFilesWithCallables(info.files) + if (files.isEmpty()) continue - IdeaModuleInfo moduleInfo = info.getModuleInfo(); - if (moduleInfo instanceof ModuleSourceInfo) { - result.addAll(getLightClassesForStaticFacadeWithSources(facadeFqName, files, moduleInfo)); + val moduleInfo = info.moduleInfo + if (moduleInfo is ModuleSourceInfo) { + result.addAll(getLightClassesForStaticFacadeWithSources(facadeFqName, files, moduleInfo)) } else { - result.addAll(getLightClassesForDecompiledFacadeFiles(files)); + result.addAll(getLightClassesForDecompiledFacadeFiles(files)) } } - return result; + return result } - private List getLightClassesForStaticFacadeWithSources( - @NotNull FqName facadeFqName, - @NotNull List facadeFiles, - @NotNull IdeaModuleInfo moduleInfo - ) { - KotlinLightClassForFacade lightClassForFacade = KotlinLightClassForFacade.Factory.createForFacade( - psiManager, facadeFqName, moduleInfo.contentScope(), facadeFiles); - return getLightClassesForFacadeWithFiles(lightClassForFacade, facadeFiles); + private fun getLightClassesForStaticFacadeWithSources( + facadeFqName: FqName, + facadeFiles: List, + moduleInfo: IdeaModuleInfo): List { + val lightClassForFacade = KotlinLightClassForFacade.createForFacade( + psiManager, facadeFqName, moduleInfo.contentScope(), facadeFiles) + return getLightClassesForFacadeWithFiles(lightClassForFacade, facadeFiles) } - @NotNull - @Override - public Collection findFilesForFacade(@NotNull FqName facadeFqName, @NotNull GlobalSearchScope scope) { - return StaticFacadeIndexUtil.findFilesForStaticFacade(facadeFqName, kotlinSourcesAndLibraries(scope, project), project); + override fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection { + return StaticFacadeIndexUtil.findFilesForStaticFacade(facadeFqName, kotlinSourcesAndLibraries(scope, project), project) } - @NotNull - private List findFacadeClassesInfos(FqName facadeFqName, GlobalSearchScope scope) { - Collection facadeFiles = findFilesForFacade(facadeFqName, scope); - return groupFilesIntoFacadeLightClassesByModuleInfo(facadeFiles); + private fun findFacadeClassesInfos(facadeFqName: FqName, scope: GlobalSearchScope): List { + val facadeFiles = findFilesForFacade(facadeFqName, scope) + return groupFilesIntoFacadeLightClassesByModuleInfo(facadeFiles) } - @NotNull - private static List groupFilesIntoFacadeLightClassesByModuleInfo(Collection facadeFiles) { - Map> filesByInfo = KotlinPackage.groupByTo( - facadeFiles, - new LinkedHashMap>(), - new Function1() { - @Override - public IdeaModuleInfo invoke(JetFile file) { - return ResolvePackage.getModuleInfo(file); - } - }); - List result = new ArrayList(); - for (Map.Entry> entry : filesByInfo.entrySet()) { - result.add(new KotlinLightFacadeClassInfo(entry.getValue(), entry.getKey())); - } - return result; - } - - @Nullable - @Override - public ClassDescriptor resolveClassToDescriptor(@NotNull JetClassOrObject classOrObject) { + override fun resolveClassToDescriptor(classOrObject: JetClassOrObject): ClassDescriptor? { try { - return (ClassDescriptor) ResolvePackage.resolveToDescriptor(classOrObject); + return classOrObject.resolveToDescriptor() as ClassDescriptor } - catch (NoDescriptorForDeclarationException e) { - return null; + catch (e: NoDescriptorForDeclarationException) { + return null } + } - @NotNull - private static List getLightClassesForDecompiledFacadeFiles(@NotNull List filesWithCallables) { - List lightClasses = new ArrayList(); - for (JetFile file : filesWithCallables) { - if (file.isCompiled()) { - lightClasses.add(createLightClassForDecompiledKotlinFile(file)); - } - } - return lightClasses; + private fun findPackageClassesInfos( + fqName: FqName, wholeScope: GlobalSearchScope): List { + val allFiles = findFilesForPackage(fqName, wholeScope) + return groupFilesIntoFacadeLightClassesByModuleInfo(allFiles) } - @NotNull - private List findPackageClassesInfos( - @NotNull FqName fqName, @NotNull GlobalSearchScope wholeScope - ) { - Collection allFiles = findFilesForPackage(fqName, wholeScope); - return groupFilesIntoFacadeLightClassesByModuleInfo(allFiles); - } + private class KotlinLightFacadeClassInfo(public val files: Collection, public val moduleInfo: IdeaModuleInfo) - private static final class KotlinLightFacadeClassInfo { - private final Collection files; - private final IdeaModuleInfo moduleInfo; + private class CachedJavaStub(public var modificationStamp: Long, public var javaFileStub: PsiJavaFileStubImpl) - public KotlinLightFacadeClassInfo(@NotNull Collection files, @NotNull IdeaModuleInfo moduleInfo) { - this.files = files; - this.moduleInfo = moduleInfo; - } + companion object { - @NotNull - public Collection getFiles() { - return files; - } + private val LOG = Logger.getInstance(javaClass()) - @NotNull - public IdeaModuleInfo getModuleInfo() { - return moduleInfo; - } - } + private fun forceResolvePackageDeclarations(files: Collection, session: KotlinCodeAnalyzer) { + for (file in files) { + // SCRIPT: not supported + if (file.isScript) continue - @Nullable - private static KotlinLightClassForDecompiledDeclaration createLightClassForDecompiledKotlinFile(@NotNull JetFile file) { - VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile == null) { - return null; - } + val packageFqName = file.packageFqName - JetClassOrObject classOrObject = singleOrNull(filterIsInstance(file.getDeclarations(), JetClassOrObject.class)); - - ClsClassImpl javaClsClass = createClsJavaClassFromVirtualFile(file, virtualFile, classOrObject); - if (javaClsClass == null) { - return null; - } - return new KotlinLightClassForDecompiledDeclaration(javaClsClass, classOrObject); - } - - @Nullable - private static ClsClassImpl createClsJavaClassFromVirtualFile( - @NotNull final JetFile decompiledKotlinFile, - @NotNull VirtualFile virtualFile, - @Nullable final JetClassOrObject decompiledClassOrObject - ) { - final PsiJavaFileStubImpl javaFileStub = getOrCreateJavaFileStub(decompiledKotlinFile, virtualFile); - if (javaFileStub == null) { - return null; - } - PsiManager manager = PsiManager.getInstance(decompiledKotlinFile.getProject()); - ClsFileImpl fakeFile = new ClsFileImpl(new ClassFileViewProvider(manager, virtualFile)) { - @NotNull - @Override - public PsiElement getNavigationElement() { - if (decompiledClassOrObject != null) { - return decompiledClassOrObject.getNavigationElement().getContainingFile(); + // make sure we create a package descriptor + val packageDescriptor = session.moduleDescriptor.getPackage(packageFqName) + if (packageDescriptor.isEmpty()) { + LOG.warn("No descriptor found for package " + packageFqName + " in file " + file.name + "\n" + file.text) + session.forceResolveAll() + continue } - return super.getNavigationElement(); + + for (declaration in file.declarations) { + if (declaration is JetFunction) { + val name = declaration.nameAsSafeName + val functions = packageDescriptor.memberScope.getFunctions(name, NoLookupLocation.FROM_IDE) + for (descriptor in functions) { + ForceResolveUtil.forceResolveAllContents(descriptor) + } + } + else if (declaration is JetProperty) { + val name = declaration.nameAsSafeName + val properties = packageDescriptor.memberScope.getProperties(name, NoLookupLocation.FROM_IDE) + for (descriptor in properties) { + ForceResolveUtil.forceResolveAllContents(descriptor) + } + } + else if (declaration is JetClassOrObject) { + // Do nothing: we are not interested in classes + } + else { + LOG.error("Unsupported declaration kind: " + declaration + " in file " + file.name + "\n" + file.text) + } + } + } + } + + private fun getLightClassForDecompiledClassOrObject(decompiledClassOrObject: JetClassOrObject): PsiClass? { + if (decompiledClassOrObject is JetEnumEntry) { + return null + } + val containingJetFile = decompiledClassOrObject.getContainingJetFile() + if (!containingJetFile.isCompiled) { + return null + } + val rootLightClassForDecompiledFile = createLightClassForDecompiledKotlinFile(containingJetFile) ?: return null + + return findCorrespondingLightClass(decompiledClassOrObject, rootLightClassForDecompiledFile) + } + + private fun findCorrespondingLightClass( + decompiledClassOrObject: JetClassOrObject, + rootLightClassForDecompiledFile: PsiClass): PsiClass { + val relativeFqName = getClassRelativeName(decompiledClassOrObject) + val iterator = relativeFqName.pathSegments().iterator() + val base = iterator.next() + assert(rootLightClassForDecompiledFile.name == base.asString()) { "Light class for file:\n" + decompiledClassOrObject.getContainingJetFile().virtualFile.canonicalPath + "\nwas expected to have name: " + base.asString() + "\n Actual: " + rootLightClassForDecompiledFile.name } + var current = rootLightClassForDecompiledFile + while (iterator.hasNext()) { + val name = iterator.next() + val innerClass = current.findInnerClassByName(name.asString(), false) + assert(innerClass != null) { "Could not find corresponding inner/nested class " + relativeFqName + " in class " + decompiledClassOrObject.fqName + "\n" + "File: " + decompiledClassOrObject.getContainingJetFile().virtualFile.name } + current = innerClass + } + return current + } + + private fun getClassRelativeName(decompiledClassOrObject: JetClassOrObject): FqName { + val name = decompiledClassOrObject.nameAsName + assert(name != null) + val parent = PsiTreeUtil.getParentOfType(decompiledClassOrObject, javaClass(), true) + if (parent == null) { + assert(decompiledClassOrObject.isTopLevel()) + return FqName.topLevel(name) + } + return getClassRelativeName(parent).child(name) + } + + private fun groupFilesIntoFacadeLightClassesByModuleInfo(facadeFiles: Collection): List { + val filesByInfo = KotlinPackage.groupByTo( + facadeFiles, + LinkedHashMap>(), + object : Function1 { + override fun invoke(file: JetFile): IdeaModuleInfo { + return file.getModuleInfo() + } + }) + val result = ArrayList() + for (entry in filesByInfo.entrySet()) { + result.add(KotlinLightFacadeClassInfo(entry.getValue(), entry.getKey())) + } + return result + } + + private fun getLightClassesForDecompiledFacadeFiles(filesWithCallables: List): List { + val lightClasses = ArrayList() + for (file in filesWithCallables) { + if (file.isCompiled) { + lightClasses.add(createLightClassForDecompiledKotlinFile(file)) + } + } + return lightClasses + } + + private fun createLightClassForDecompiledKotlinFile(file: JetFile): KotlinLightClassForDecompiledDeclaration? { + val virtualFile = file.virtualFile ?: return null + + val classOrObject = singleOrNull(filterIsInstance(file.declarations, javaClass())) + + val javaClsClass = createClsJavaClassFromVirtualFile(file, virtualFile, classOrObject) ?: return null + return KotlinLightClassForDecompiledDeclaration(javaClsClass, classOrObject) + } + + private fun createClsJavaClassFromVirtualFile( + decompiledKotlinFile: JetFile, + virtualFile: VirtualFile, + decompiledClassOrObject: JetClassOrObject?): ClsClassImpl? { + val javaFileStub = getOrCreateJavaFileStub(decompiledKotlinFile, virtualFile) ?: return null + val manager = PsiManager.getInstance(decompiledKotlinFile.project) + val fakeFile = object : ClsFileImpl(ClassFileViewProvider(manager, virtualFile)) { + override fun getNavigationElement(): PsiElement { + if (decompiledClassOrObject != null) { + return decompiledClassOrObject.navigationElement.containingFile + } + return super.getNavigationElement() + } + + override fun getStub(): PsiClassHolderFileStub { + return javaFileStub + } + + override fun getMirror(): PsiElement { + return decompiledKotlinFile + } + } + fakeFile.isPhysical = false + javaFileStub.setPsi(fakeFile) + return single(fakeFile.classes) as ClsClassImpl + } + + private val cachedJavaStubKey = Key.create("CACHED_JAVA_STUB") + + private fun getOrCreateJavaFileStub( + decompiledKotlinFile: JetFile, + virtualFile: VirtualFile): PsiJavaFileStubImpl? { + val cachedJavaStub = decompiledKotlinFile.getUserData(cachedJavaStubKey) + val fileModificationStamp = virtualFile.modificationStamp + if (cachedJavaStub != null && cachedJavaStub.modificationStamp == fileModificationStamp) { + return cachedJavaStub.javaFileStub + } + val stub = createStub(virtualFile) as PsiJavaFileStubImpl? + if (stub != null) { + decompiledKotlinFile.putUserData(cachedJavaStubKey, CachedJavaStub(fileModificationStamp, stub)) + } + return stub + } + + private fun createStub(file: VirtualFile): PsiJavaFileStub? { + if (file.fileType !== JavaClassFileType.INSTANCE) return null + + try { + return ClsFileImpl.buildFileStub(file, file.contentsToByteArray()) + } + catch (e: ClsFormatException) { + LOG.debug(e) + } + catch (e: IOException) { + LOG.debug(e) } - @NotNull - @Override - public PsiClassHolderFileStub getStub() { - return javaFileStub; - } - - @Override - public PsiElement getMirror() { - return decompiledKotlinFile; - } - }; - fakeFile.setPhysical(false); - javaFileStub.setPsi(fakeFile); - return (ClsClassImpl) single(fakeFile.getClasses()); - } - - private final static Key cachedJavaStubKey = Key.create("CACHED_JAVA_STUB"); - - private static class CachedJavaStub { - public CachedJavaStub(long modificationStamp, @NotNull PsiJavaFileStubImpl javaFileStub) { - this.modificationStamp = modificationStamp; - this.javaFileStub = javaFileStub; + LOG.error("Failed to build java cls class for " + file.canonicalPath!!) + return null } - - public long modificationStamp; - public PsiJavaFileStubImpl javaFileStub; - } - - @Nullable - private static PsiJavaFileStubImpl getOrCreateJavaFileStub( - @NotNull JetFile decompiledKotlinFile, - @NotNull VirtualFile virtualFile) { - CachedJavaStub cachedJavaStub = decompiledKotlinFile.getUserData(cachedJavaStubKey); - long fileModificationStamp = virtualFile.getModificationStamp(); - if (cachedJavaStub != null && cachedJavaStub.modificationStamp == fileModificationStamp) { - return cachedJavaStub.javaFileStub; - } - PsiJavaFileStubImpl stub = (PsiJavaFileStubImpl) createStub(virtualFile); - if (stub != null) { - decompiledKotlinFile.putUserData(cachedJavaStubKey, new CachedJavaStub(fileModificationStamp, stub)); - } - return stub; - } - - @Nullable - private static PsiJavaFileStub createStub(@NotNull VirtualFile file) { - if (file.getFileType() != JavaClassFileType.INSTANCE) return null; - - try { - return ClsFileImpl.buildFileStub(file, file.contentsToByteArray()); - } - catch (ClsFormatException e) { - LOG.debug(e); - } - catch (IOException e) { - LOG.debug(e); - } - LOG.error("Failed to build java cls class for " + file.getCanonicalPath()); - return null; } }