@Nullable private static PsiClass getLightClassForDecompiledPackage( @NotNull FqName packageFqName, @NotNull List<JetFile> filesWithCallables) { JetFile firstFile = filesWithCallables.iterator().next(); if (firstFile.isCompiled()) { if (filesWithCallables.size() > 1) { LOG.error("Several files with callables for package: " + packageFqName); } return createLightClassForDecompiledKotlinFile(firstFile); } return null; }
@NotNull @Override public LightClassConstructionContext getContextForPackage(@NotNull Collection<JetFile> files) { assert !files.isEmpty() : "No files in package"; List<JetFile> sortedFiles = new ArrayList<JetFile>(files); Collections.sort(sortedFiles, scopeFileComparator); JetFile file = sortedFiles.get(0); ResolveSessionForBodies session = KotlinCacheService.getInstance(file.getProject()).getLazyResolveSession(file); forceResolvePackageDeclarations(files, session); return new LightClassConstructionContext( session.getBindingContext(), session.getModuleDescriptor()); }
@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; return findCorrespondingLightClass(decompiledClassOrObject, rootLightClassForDecompiledFile); }
@Nullable private static KotlinLightClassForDecompiledDeclaration createLightClassForDecompiledKotlinFile( @NotNull JetFile file) { VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile == null) { return null; } JetClassOrObject classOrObject = singleOrNull(filterIsInstance(file.getDeclarations(), JetClassOrObject.class)); ClsClassImpl javaClsClass = createClsJavaClassFromVirtualFile(file, virtualFile, classOrObject); if (javaClsClass == null) { return null; } return new KotlinLightClassForDecompiledDeclaration(javaClsClass, classOrObject); }
private static void forceResolvePackageDeclarations( @NotNull Collection<JetFile> 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<FunctionDescriptor> functions = packageDescriptor.getMemberScope().getFunctions(name, LookupLocation.NO_LOCATION); for (FunctionDescriptor descriptor : functions) { ForceResolveUtil.forceResolveAllContents(descriptor); } } else if (declaration instanceof JetProperty) { JetProperty jetProperty = (JetProperty) declaration; Name name = jetProperty.getNameAsSafeName(); Collection<VariableDescriptor> properties = packageDescriptor.getMemberScope().getProperties(name, LookupLocation.NO_LOCATION); 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()); } } } }
@Nullable private static ClsClassImpl createClsJavaClassFromVirtualFile( @NotNull final JetFile decompiledKotlinFile, @NotNull VirtualFile virtualFile, @Nullable final JetClassOrObject decompiledClassOrObject) { final PsiJavaFileStubImpl javaFileStub = getOrCreateJavaFileStub(virtualFile); if (javaFileStub == null) { return null; } PsiManager manager = PsiManager.getInstance(decompiledKotlinFile.getProject()); ClsFileImpl fakeFile = new ClsFileImpl((PsiManagerImpl) manager, new ClassFileViewProvider(manager, virtualFile)) { @NotNull @Override public PsiElement getNavigationElement() { if (decompiledClassOrObject != null) { return decompiledClassOrObject.getNavigationElement().getContainingFile(); } return super.getNavigationElement(); } @NotNull @Override public PsiClassHolderFileStub getStub() { return javaFileStub; } @Override public PsiElement getMirror() { return decompiledKotlinFile; } }; fakeFile.setPhysical(false); javaFileStub.setPsi(fakeFile); return (ClsClassImpl) single(fakeFile.getClasses()); }