Introduce ScriptDependenciesSourceModuleInfo

Implement SourceForBinaryModuleInfo api to support navigation
Support in getModuleInfo and KotlinCacheServiceImpl
This commit is contained in:
Pavel V. Talanov
2017-03-18 22:00:34 +03:00
parent 434018f679
commit 88447d69cb
5 changed files with 71 additions and 19 deletions
@@ -218,22 +218,14 @@ class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo,
}
data class LibrarySourceInfo(val project: Project, val library: Library) : IdeaModuleInfo, SourceForBinaryModuleInfo {
override val moduleOrigin: ModuleOrigin
get() = ModuleOrigin.OTHER
override val name: Name = Name.special("<sources for library ${library.name}>")
override fun contentScope(): GlobalSearchScope = GlobalSearchScope.EMPTY_SCOPE
override fun sourceScope(): GlobalSearchScope = LibrarySourceScope(project, library)
override val isLibrary: Boolean
get() = true
override fun dependencies(): List<IdeaModuleInfo> {
return listOf(this) + LibraryInfo(project, library).dependencies()
}
override fun modulesWhoseInternalsAreVisible(): Collection<ModuleInfo> {
return listOf(LibraryInfo(project, library))
}
@@ -321,4 +313,16 @@ interface BinaryModuleInfo : IdeaModuleInfo {
interface SourceForBinaryModuleInfo : IdeaModuleInfo {
val binariesModuleInfo: BinaryModuleInfo
fun sourceScope(): GlobalSearchScope
// module infos for library source do not have contents in the following sense:
// we can not provide a collection of files that is supposed to be analyzed in IDE independently
//
// as of now each source file is analyzed separately and depends on corresponding binaries
// see KotlinCacheServiceImpl#createFacadeForSyntheticFiles
override fun contentScope(): GlobalSearchScope = GlobalSearchScope.EMPTY_SCOPE
override fun dependencies() = listOf(this) + binariesModuleInfo.dependencies()
override val moduleOrigin: ModuleOrigin
get() = ModuleOrigin.OTHER
}
@@ -219,9 +219,6 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
)
}
syntheticFileModule is ScriptDependenciesModuleInfo -> {
createFacadeForScriptDependencies(syntheticFileModule, files)
}
syntheticFileModule is ScriptModuleInfo -> {
val facadeForScriptDependencies = getFacadeForScriptDependencies(syntheticFileModule)
val globalContext = facadeForScriptDependencies.globalContext.contextWithNewLockAndCompositeExceptionTracker()
@@ -235,6 +232,23 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
)
)
}
syntheticFileModule is ScriptDependenciesModuleInfo -> {
createFacadeForScriptDependencies(syntheticFileModule, files)
}
syntheticFileModule is ScriptDependenciesSourceModuleInfo -> {
// TODO: can be optimized by caching facadeForScriptDependencies
val facadeForScriptDependencies = createFacadeForScriptDependencies(syntheticFileModule.binariesModuleInfo, files)
val globalContext = facadeForScriptDependencies.globalContext.contextWithNewLockAndCompositeExceptionTracker()
ProjectResolutionFacade(
"facadeForSynthetic in ScriptDependenciesSourceModuleInfo",
project, globalContext,
makeGlobalResolveSessionProvider(
reuseDataFrom = facadeForScriptDependencies,
allModules = syntheticFileModule.dependencies(),
moduleFilter = { it == syntheticFileModule }
)
)
}
syntheticFileModule is LibrarySourceInfo || syntheticFileModule is NotUnderContentRootModuleInfo -> {
val librariesFacade = librariesFacade(targetPlatform, sdk)
@@ -74,7 +74,7 @@ class ScriptDependenciesModuleInfo(
val project: Project,
val dependencies: KotlinScriptExternalDependencies?,
val scriptModuleInfo: ScriptModuleInfo?
): IdeaModuleInfo {
): IdeaModuleInfo, BinaryModuleInfo {
override fun dependencies() = (listOf(this) + sdkDependencies(dependencies, project))
override val name = Name.special("<Script dependencies>")
@@ -98,4 +98,21 @@ class ScriptDependenciesModuleInfo(
override val moduleOrigin: ModuleOrigin
get() = ModuleOrigin.LIBRARY
override val sourcesModuleInfo: SourceForBinaryModuleInfo?
get() = ScriptDependenciesSourceModuleInfo(project)
}
data class ScriptDependenciesSourceModuleInfo(
val project: Project
): IdeaModuleInfo, SourceForBinaryModuleInfo {
override val name = Name.special("<Source for script dependencies>")
override val binariesModuleInfo: ScriptDependenciesModuleInfo
get() = ScriptDependenciesModuleInfo(project, null, null)
override fun sourceScope(): GlobalSearchScope = KotlinSourceFilterScope.librarySources(
KotlinScriptConfigurationManager.getInstance(project).getAllLibrarySourcesScope(), project
)
}
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtLightClassForDecompiledDeclaration
import org.jetbrains.kotlin.idea.core.script.KotlinScriptConfigurationManager
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.idea.util.isKotlinBinary
import org.jetbrains.kotlin.idea.util.isInSourceContentWithoutInjected
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
@@ -81,7 +82,11 @@ private fun PsiElement.getModuleInfo(onFailure: (String) -> IdeaModuleInfo?): Id
)
}
fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFile, treatAsLibrarySource: Boolean): IdeaModuleInfo {
fun getModuleInfoByVirtualFile(
project: Project, virtualFile: VirtualFile
): IdeaModuleInfo = getModuleInfoByVirtualFile(project, virtualFile, treatAsLibrarySource = false)
private fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFile, treatAsLibrarySource: Boolean): IdeaModuleInfo {
val projectFileIndex = ProjectFileIndex.SERVICE.getInstance(project)
val module = projectFileIndex.getModuleForFile(virtualFile)
@@ -130,8 +135,18 @@ fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFile, treat
return ScriptModuleInfo(project, virtualFile, scriptDefinition)
}
if (KotlinScriptConfigurationManager.getInstance(project).getAllScriptsClasspathScope().contains(virtualFile)) {
return ScriptDependenciesModuleInfo(project, null, null)
val isBinary = virtualFile.isKotlinBinary()
val scriptConfigurationManager = KotlinScriptConfigurationManager.getInstance(project)
if (isBinary && virtualFile in scriptConfigurationManager.getAllScriptsClasspathScope()) {
if (treatAsLibrarySource) {
return ScriptDependenciesSourceModuleInfo(project)
}
else {
return ScriptDependenciesModuleInfo(project, null, null)
}
}
if (!isBinary && virtualFile in scriptConfigurationManager.getAllLibrarySourcesScope()) {
return ScriptDependenciesSourceModuleInfo(project)
}
return NotUnderContentRootModuleInfo
@@ -32,7 +32,9 @@ import org.jetbrains.kotlin.idea.core.script.KotlinScriptConfigurationManager
import org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInFileType
import org.jetbrains.kotlin.idea.util.application.runReadAction
private val classFileLike = listOf(JavaClassFileType.INSTANCE, KotlinBuiltInFileType, KotlinModuleFileType.INSTANCE)
private val kotlinBinaries = listOf(JavaClassFileType.INSTANCE, KotlinBuiltInFileType, KotlinModuleFileType.INSTANCE)
fun VirtualFile.isKotlinBinary(): Boolean = fileType in kotlinBinaries
fun FileIndex.isInSourceContentWithoutInjected(file: VirtualFile): Boolean {
return file !is VirtualFileWindow && isInSourceContent(file)
@@ -51,15 +53,15 @@ object ProjectRootsUtil {
// NOTE: the following is a workaround for cases when class files are under library source roots and source files are under class roots
val canContainClassFiles = file.fileType == ArchiveFileType.INSTANCE || file.isDirectory
val isClassFile = file.fileType in classFileLike
val isBinary = file.isKotlinBinary()
val scriptConfigurationManager = if (includeScriptDependencies) KotlinScriptConfigurationManager.getInstance(project) else null
if (includeLibraryClasses && (isClassFile || canContainClassFiles)) {
if (includeLibraryClasses && (isBinary || canContainClassFiles)) {
if (fileIndex.isInLibraryClasses(file)) return true
if (scriptConfigurationManager?.getAllScriptsClasspathScope()?.contains(file) == true) return true
}
if (includeLibrarySource && !isClassFile) {
if (includeLibrarySource && !isBinary) {
if (fileIndex.isInLibrarySource(file)) return true
if (scriptConfigurationManager?.getAllLibrarySourcesScope()?.contains(file) == true) return true
}