Improve modular JDK root module detection

According to the spec, "java.se" and every other non-"java.*" module
that exports at least one package without qualification, is a root.
Currently we only support compilation of a single unnamed module, and
apparently unnamed module should read all root modules.

 #KT-18180 Fixed
This commit is contained in:
Alexander Udalov
2017-03-31 16:17:07 +03:00
parent 5042bbe4a1
commit 1572d2cf2b
4 changed files with 123 additions and 22 deletions
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve.jvm.modules
interface JavaModuleFinder {
fun findModule(name: String): JavaModuleInfo?
}
@@ -18,22 +18,25 @@ package org.jetbrains.kotlin.resolve.jvm.modules
import org.jetbrains.kotlin.storage.LockBasedStorageManager
class JavaModuleGraph(getModuleInfo: (String) -> JavaModuleInfo) {
private val moduleInfo: (String) -> JavaModuleInfo = LockBasedStorageManager.NO_LOCKS.createMemoizedFunction(getModuleInfo)
class JavaModuleGraph(finder: JavaModuleFinder) {
private val moduleInfo: (String) -> JavaModuleInfo? =
LockBasedStorageManager.NO_LOCKS.createMemoizedFunctionWithNullableValues(finder::findModule)
fun getAllReachable(rootModules: List<String>): List<String> {
val visited = linkedSetOf<String>()
fun getAllDependencies(moduleNames: List<String>): List<String> {
// Every module implicitly depends on java.base
val visited = linkedSetOf("java.base")
fun dfs(module: String) {
if (!visited.add(module)) return
for (dependency in moduleInfo(module).requires) {
val moduleInfo = moduleInfo(module) ?: return
for (dependency in moduleInfo.requires) {
if (dependency.isTransitive) {
dfs(dependency.moduleName)
}
}
}
rootModules.forEach(::dfs)
moduleNames.forEach(::dfs)
return visited.toList()
}
}