JS: fix clash between sources and metadata in one library

This commit is contained in:
Michael Nedzelsky
2015-03-12 15:16:47 +03:00
parent 577921d4f7
commit e3bd99d510
4 changed files with 56 additions and 35 deletions
+1
View File
@@ -355,6 +355,7 @@
</closure-compiler> </closure-compiler>
<jar jarfile="${kotlin-home}/lib/kotlin-jslib.jar" duplicate="fail"> <jar jarfile="${kotlin-home}/lib/kotlin-jslib.jar" duplicate="fail">
<resources refid="js.lib.files" />
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/> <zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
<zipfileset file="${output}/kotlin.js" prefix=""/> <zipfileset file="${output}/kotlin.js" prefix=""/>
<zipfileset file="${output}/${compiled.stdlib.meta.js}" prefix=""/> <zipfileset file="${output}/${compiled.stdlib.meta.js}" prefix=""/>
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.context.GlobalContext
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.di.InjectorForLazyResolve import org.jetbrains.kotlin.di.InjectorForLazyResolve
import org.jetbrains.kotlin.idea.framework.JsHeaderLibraryDetectionUtil
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
import org.jetbrains.kotlin.js.resolve.KotlinJsCheckerProvider import org.jetbrains.kotlin.js.resolve.KotlinJsCheckerProvider
import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap
@@ -61,12 +62,15 @@ public object JsAnalyzerFacade : AnalyzerFacade<JsResolverForModule, PlatformAna
var packageFragmentProvider = resolveSession.getPackageFragmentProvider() var packageFragmentProvider = resolveSession.getPackageFragmentProvider()
if (moduleInfo is LibraryInfo) { if (moduleInfo is LibraryInfo) {
val providers = moduleInfo.library.getFiles(OrderRootType.CLASSES) val files = moduleInfo.library.getFiles(OrderRootType.CLASSES)
.flatMap { KotlinJavascriptMetadataUtils.loadMetadata(PathUtil.getLocalPath(it)!!) } if (!JsHeaderLibraryDetectionUtil.isJsHeaderLibraryWithSources(files.toList())) {
.flatMap { KotlinJavascriptSerializationUtil.getPackageFragmentProviders(moduleDescriptor, it.body) } val providers = moduleInfo.library.getFiles(OrderRootType.CLASSES)
.flatMap { KotlinJavascriptMetadataUtils.loadMetadata(PathUtil.getLocalPath(it)!!) }
.flatMap { KotlinJavascriptSerializationUtil.getPackageFragmentProviders(moduleDescriptor, it.body) }
if (providers.isNotEmpty()) { if (providers.isNotEmpty()) {
packageFragmentProvider = CompositePackageFragmentProvider(listOf(packageFragmentProvider) + providers) packageFragmentProvider = CompositePackageFragmentProvider(listOf(packageFragmentProvider) + providers)
}
} }
} }
@@ -48,10 +48,15 @@ public final class DecompiledNavigationUtils {
) { ) {
VirtualFile virtualFile; VirtualFile virtualFile;
if (JsProjectDetector.isJsProject(project) && NavigationPackage.getKotlinJavascriptLibrary(referencedDescriptor, project) != null) { if (JsProjectDetector.isJsProject(project)) {
JsMetaFileVirtualFileHolder system = JsMetaFileVirtualFileHolder.getInstance(project); if (NavigationPackage.getKotlinJavascriptLibraryWithMetadata(referencedDescriptor, project) != null) {
virtualFile = system.getFile(referencedDescriptor); JsMetaFileVirtualFileHolder system = JsMetaFileVirtualFileHolder.getInstance(project);
if (virtualFile == null) return null; virtualFile = system.getFile(referencedDescriptor);
if (virtualFile == null) return null;
}
else {
return null;
}
} }
else { else {
virtualFile = findVirtualFileContainingDescriptor(project, referencedDescriptor); virtualFile = findVirtualFileContainingDescriptor(project, referencedDescriptor);
@@ -20,7 +20,9 @@ import com.intellij.ide.highlighter.JavaClassFileType
import com.intellij.openapi.fileTypes.FileType import com.intellij.openapi.fileTypes.FileType
import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.ProjectRootModificationTracker import com.intellij.openapi.roots.ProjectRootModificationTracker
import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
@@ -33,57 +35,66 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.idea.caches.resolve.LIBRARY_NAME_PREFIX 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.idea.project.ProjectStructureUtil
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import kotlin.platform.platformStatic import kotlin.platform.platformStatic
fun getKotlinJavascriptLibrary(descriptor: DeclarationDescriptor, project: Project): Library? { fun getKotlinJavascriptLibraryWithMetadata(descriptor: DeclarationDescriptor, project: Project): Library? {
val containingPackageFragment = DescriptorUtils.getParentOfType<PackageFragmentDescriptor>(descriptor, javaClass<PackageFragmentDescriptor>()) val containingPackageFragment = DescriptorUtils.getParentOfType<PackageFragmentDescriptor>(descriptor, javaClass<PackageFragmentDescriptor>())
if (containingPackageFragment == null) return null if (containingPackageFragment == null) return null
val module = DescriptorUtils.getContainingModule(descriptor) val module = DescriptorUtils.getContainingModule(descriptor)
assert(module is ModuleDescriptorImpl) assert(module is ModuleDescriptorImpl)
var moduleName = getModuleName(module) return getKotlinJavascriptLibrary(module, project)
return getKotlinJavascriptLibrary(moduleName, project)
}
fun getKotlinJavascriptLibrary(libraryName: String, project: Project): Library? {
var library: Library? = null
val jsModules = ModuleManager.getInstance(project).getModules().filter { (ProjectStructureUtil.isJsKotlinModule(it)) }
jsModules.forEach { module ->
ModuleRootManager.getInstance(module).orderEntries().librariesOnly().forEachLibrary {
if (it.getName() == libraryName) { library = it; false } else true
}
}
return library
} }
fun getKotlinJavascriptLibrary(file: VirtualFile, project: Project): Library? { fun getKotlinJavascriptLibrary(file: VirtualFile, project: Project): Library? {
val module = file.getUserData(JsMetaFileVirtualFileHolder.MODULE_DESCRIPTOR_KEY) val module = file.getUserData(JsMetaFileVirtualFileHolder.MODULE_DESCRIPTOR_KEY)
if (module == null) return null if (module == null) return null
var moduleName = getModuleName(module) return getKotlinJavascriptLibrary(module, project)
return getKotlinJavascriptLibrary(moduleName, project)
} }
private fun getModuleName(module: ModuleDescriptor): String { private fun Library.isWithoutSources(): Boolean =
var moduleName = module.getName().asString() !JsHeaderLibraryDetectionUtil.isJsHeaderLibraryWithSources(this.getFiles(OrderRootType.CLASSES).toList())
moduleName = moduleName.substring(1, moduleName.length() - 1)
if (moduleName.startsWith(LIBRARY_NAME_PREFIX)) { // getName() could return null for module level library
moduleName = moduleName.substring(LIBRARY_NAME_PREFIX.length()) private fun Library.safeGetName(): String = this.getName() ?: "null"
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
}
}
}
} }
return moduleName return null
}
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) { class JsMetaFileVirtualFileHolder private(val myProject: Project) {
default object { class object {
public val MODULE_DESCRIPTOR_KEY: Key<ModuleDescriptorImpl> = Key.create("MODULE_DESCRIPTOR") public val MODULE_DESCRIPTOR_KEY: Key<ModuleDescriptorImpl> = Key.create("MODULE_DESCRIPTOR")
public val PACKAGE_FQNAME_KEY: Key<FqName> = Key.create("PACKAGE_FQNAME_KEY") 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") private val JS_META_FILE_HOLDER_KEY: Key<JsMetaFileVirtualFileHolder> = Key.create("JS_META_FILE_HOLDER_KEY")