JsMetaFileUtils: add some useful code, remove unnecessary parts
This commit is contained in:
+32
-115
@@ -16,139 +16,56 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.decompiler.navigation
|
||||
|
||||
import com.intellij.ide.highlighter.JavaClassFileType
|
||||
import com.intellij.openapi.fileTypes.FileType
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.LibraryOrderEntry
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.roots.OrderRootType
|
||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.testFramework.BinaryLightVirtualFile
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.LIBRARY_NAME_PREFIX
|
||||
import org.jetbrains.kotlin.idea.framework.JsHeaderLibraryDetectionUtil
|
||||
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import kotlin.platform.platformStatic
|
||||
import org.jetbrains.kotlin.serialization.js.isDefaultPackageMetafile
|
||||
import org.jetbrains.kotlin.serialization.js.isPackageClassFqName
|
||||
|
||||
fun getKotlinJavascriptLibraryWithMetadata(descriptor: DeclarationDescriptor, project: Project): Library? {
|
||||
val containingPackageFragment = DescriptorUtils.getParentOfType<PackageFragmentDescriptor>(descriptor, javaClass<PackageFragmentDescriptor>())
|
||||
if (containingPackageFragment == null) return null
|
||||
public object JsMetaFileUtils {
|
||||
|
||||
val module = DescriptorUtils.getContainingModule(descriptor)
|
||||
assert(module is ModuleDescriptorImpl)
|
||||
public fun getPackageFqName(file: VirtualFile): FqName = getPackageFqName(getRelativeToRootPath(file))
|
||||
|
||||
return getKotlinJavascriptLibrary(module, project)
|
||||
}
|
||||
public fun getClassFqName(file: VirtualFile): FqName = getClassFqName(getRelativeToRootPath(file))
|
||||
|
||||
fun getKotlinJavascriptLibrary(file: VirtualFile, project: Project): Library? {
|
||||
val module = file.getUserData(JsMetaFileVirtualFileHolder.MODULE_DESCRIPTOR_KEY)
|
||||
if (module == null) return null
|
||||
public fun getClassId(file: VirtualFile): ClassId = getClassId(getRelativeToRootPath(file))
|
||||
|
||||
return getKotlinJavascriptLibrary(module, project)
|
||||
}
|
||||
public fun isPackageHeader(file: VirtualFile): Boolean = isPackageHeader(getRelativeToRootPath(file))
|
||||
|
||||
private fun Library.isWithoutSources(): Boolean =
|
||||
!JsHeaderLibraryDetectionUtil.isJsHeaderLibraryWithSources(this.getFiles(OrderRootType.CLASSES).toList())
|
||||
public fun getModuleDirectory(file: VirtualFile): VirtualFile =
|
||||
getRoot(file).findChild(getModuleName(getRelativeToRootPath(file)))!!
|
||||
|
||||
// getName() could return null for module level library
|
||||
private fun Library.safeGetName(): String = this.getName() ?: "null"
|
||||
private fun getRelativeToRootPath(file: VirtualFile): String = VfsUtilCore.getRelativePath(file, getRoot(file))!!
|
||||
|
||||
private fun getKotlinJavascriptLibrary(module: ModuleDescriptor, project: Project): Library? {
|
||||
val libraryName = getLibraryName(module)
|
||||
if (libraryName == null) return null
|
||||
|
||||
val jsIdeaModules = ModuleManager.getInstance(project).getModules().filter { (ProjectStructureUtil.isJsKotlinModule(it)) }
|
||||
for(ideaModule in jsIdeaModules) {
|
||||
for(orderEntry in ModuleRootManager.getInstance(ideaModule).getOrderEntries()) {
|
||||
if (orderEntry is LibraryOrderEntry) {
|
||||
val library = orderEntry.getLibrary()
|
||||
if (library != null && library.safeGetName() == libraryName && library.isWithoutSources()) {
|
||||
return library
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun getClassFqName(relPath: String): FqName {
|
||||
val pathToFile = relPath.substringAfter(VfsUtilCore.VFS_SEPARATOR_CHAR)
|
||||
return FqName(pathToFile.substringBeforeLast('.').replace(VfsUtilCore.VFS_SEPARATOR_CHAR, '.'))
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
private fun getClassId(relPath: String): ClassId {
|
||||
val classFqName = getClassFqName(relPath)
|
||||
val packageFqName = getPackageFqName(relPath)
|
||||
|
||||
private fun getLibraryName(module: ModuleDescriptor): String? {
|
||||
var moduleName = module.getName().asString()
|
||||
moduleName = moduleName.substring(1, moduleName.length() - 1)
|
||||
|
||||
if (!moduleName.startsWith(LIBRARY_NAME_PREFIX)) return null
|
||||
|
||||
return moduleName.substring(LIBRARY_NAME_PREFIX.length())
|
||||
}
|
||||
|
||||
|
||||
class JsMetaFileVirtualFileHolder private(val myProject: Project) {
|
||||
companion object {
|
||||
public val MODULE_DESCRIPTOR_KEY: Key<ModuleDescriptorImpl> = Key.create("MODULE_DESCRIPTOR")
|
||||
public val PACKAGE_FQNAME_KEY: Key<FqName> = Key.create("PACKAGE_FQNAME_KEY")
|
||||
private val JS_META_FILE_HOLDER_KEY: Key<JsMetaFileVirtualFileHolder> = Key.create("JS_META_FILE_HOLDER_KEY")
|
||||
|
||||
platformStatic
|
||||
public fun getInstance(project: Project): JsMetaFileVirtualFileHolder {
|
||||
var holder = project.getUserData(JS_META_FILE_HOLDER_KEY)
|
||||
|
||||
if (holder == null) {
|
||||
holder = JsMetaFileVirtualFileHolder(project)
|
||||
project.putUserData(JS_META_FILE_HOLDER_KEY, holder)
|
||||
}
|
||||
|
||||
return holder
|
||||
}
|
||||
val name = classFqName.shortName().asString().substringBeforeLast('.')
|
||||
return ClassId(packageFqName, FqName(name), false)
|
||||
}
|
||||
|
||||
private val cachedFileMap = CachedValuesManager.getManager(myProject).createCachedValue( {
|
||||
CachedValueProvider.Result(hashMapOf<String, VirtualFile>(), ProjectRootModificationTracker.getInstance(myProject))
|
||||
}, false)
|
||||
private fun getPackageFqName(relPath: String): FqName {
|
||||
val pathToFile = relPath.substringAfter(VfsUtilCore.VFS_SEPARATOR_CHAR)
|
||||
if (isDefaultPackageMetafile(pathToFile)) return FqName.ROOT
|
||||
|
||||
fun getFile(descriptor: DeclarationDescriptor): VirtualFile? {
|
||||
val containingPackageFragment = DescriptorUtils.getParentOfType<PackageFragmentDescriptor>(descriptor, javaClass<PackageFragmentDescriptor>())
|
||||
if (containingPackageFragment == null) return null
|
||||
|
||||
val packageName = DescriptorUtils.getFqName(containingPackageFragment).asString()
|
||||
|
||||
val module = DescriptorUtils.getContainingModule(descriptor)
|
||||
assert(module is ModuleDescriptorImpl)
|
||||
|
||||
var moduleName = module.getName().asString()
|
||||
moduleName = moduleName.substring(1, moduleName.length() - 1)
|
||||
if (moduleName.startsWith("library ")) {
|
||||
moduleName = moduleName.substring(8)
|
||||
}
|
||||
|
||||
val fileName = "${moduleName}/${packageName}.meta"
|
||||
val fileMap = cachedFileMap.getValue()
|
||||
|
||||
var result = fileMap[fileName]
|
||||
|
||||
if (result == null) {
|
||||
result = JsMetaFileBinaryLightVirtualFile(fileName)
|
||||
fileMap[fileName] = result!!
|
||||
}
|
||||
|
||||
result?.putUserData(MODULE_DESCRIPTOR_KEY, module as ModuleDescriptorImpl)
|
||||
result?.putUserData(PACKAGE_FQNAME_KEY, FqName(packageName))
|
||||
|
||||
return result
|
||||
val name = pathToFile.substringBeforeLast(VfsUtilCore.VFS_SEPARATOR_CHAR)
|
||||
return FqName(name.replace(VfsUtilCore.VFS_SEPARATOR_CHAR, '.'))
|
||||
}
|
||||
|
||||
private inner class JsMetaFileBinaryLightVirtualFile(name: String) : BinaryLightVirtualFile(name) {
|
||||
override fun getFileType(): FileType = JavaClassFileType.INSTANCE
|
||||
private fun getModuleName(relPath: String): String = relPath.substringBefore(VfsUtilCore.VFS_SEPARATOR_CHAR)
|
||||
|
||||
private fun isPackageHeader(relPath: String): Boolean {
|
||||
val classFqName = JsMetaFileUtils.getClassFqName(relPath)
|
||||
return classFqName.isPackageClassFqName()
|
||||
}
|
||||
|
||||
private fun getRoot(file: VirtualFile): VirtualFile = if (file.getParent() == null) file else getRoot(file.getParent())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user