forbid compiling code in packages with names starting with 'kotlin' unless the -Xallow-kotlin-package command line option is specified

This commit is contained in:
Dmitry Jemerov
2016-01-13 19:04:16 +01:00
parent 6b354748ba
commit f3faa10fcc
11 changed files with 51 additions and 2 deletions
@@ -67,6 +67,9 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments {
@Argument(value = "Xmultifile-facades-open", description = "Compile multifile facade classes as open")
public boolean multifileFacadesOpen;
@Argument(value = "Xallow-kotlin-package", description = "Allow compiling code in package 'kotlin'")
public boolean allowKotlinPackage;
// Paths to output directories for friend modules.
public String[] friendPaths;
@@ -26,6 +26,8 @@ public class CLIConfigurationKeys {
CompilerConfigurationKey.create("message collector");
public static final CompilerConfigurationKey<List<CompilerPlugin>> COMPILER_PLUGINS =
CompilerConfigurationKey.create("compiler plugins");
public static final CompilerConfigurationKey<Boolean> ALLOW_KOTLIN_PACKAGE =
CompilerConfigurationKey.create("allow kotlin package");
private CLIConfigurationKeys() {
}
@@ -275,6 +275,7 @@ open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
configuration.put(JVMConfigurationKeys.DISABLE_INLINE, arguments.noInline)
configuration.put(JVMConfigurationKeys.DISABLE_OPTIMIZATION, arguments.noOptimize)
configuration.put(JVMConfigurationKeys.MULTIFILE_FACADES_OPEN, arguments.multifileFacadesOpen);
configuration.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage);
}
private fun getClasspath(paths: KotlinPaths, arguments: K2JVMCompilerArguments): List<File> {
@@ -21,7 +21,9 @@ import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.CompilerPluginContext
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageUtil
import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.cli.jvm.config.*
@@ -35,6 +37,8 @@ import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.isSubpackageOf
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
@@ -106,10 +110,11 @@ object KotlinToJVMBytecodeCompiler {
for (module in chunk) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val jetFiles = CompileEnvironmentUtil.getKtFiles(
val ktFiles = CompileEnvironmentUtil.getKtFiles(
environment.project, getAbsolutePaths(directory, module)) { s -> throw IllegalStateException("Should have been checked before: " + s) }
if (!checkKotlinPackageUsage(environment, ktFiles)) return false
val moduleOutputDirectory = File(module.getOutputDirectory())
val generationState = generate(environment, result, jetFiles, module, moduleOutputDirectory,
val generationState = generate(environment, result, ktFiles, module, moduleOutputDirectory,
module.getModuleName())
outputFiles.put(module, generationState.factory)
}
@@ -173,6 +178,7 @@ object KotlinToJVMBytecodeCompiler {
moduleVisibilityManager.addFriendPath(path)
}
if (!checkKotlinPackageUsage(environment, environment.getSourceFiles())) return false
val generationState = analyzeAndGenerate(environment) ?: return false
val mainClass = findMainClass(generationState, environment.getSourceFiles())
@@ -360,6 +366,23 @@ object KotlinToJVMBytecodeCompiler {
return generationState
}
private fun checkKotlinPackageUsage(environment: KotlinCoreEnvironment, files: Collection<KtFile>): Boolean {
if (environment.configuration.get(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE) == true) {
return true
}
val messageCollector = environment.configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
val kotlinPackage = FqName.topLevel(Name.identifier("kotlin"))
files.forEach {
if (it.packageFqName.isSubpackageOf(kotlinPackage)) {
messageCollector.report(CompilerMessageSeverity.ERROR,
"Only the Kotlin standard library is allowed to use the 'kotlin' package",
MessageUtil.psiElementToMessageLocation(it.packageDirective!!))
return false
}
}
return true
}
fun KotlinCoreEnvironment.messageCollector(): MessageCollector {
val result = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
assert(result != null) { "Message collector not specified in compiler configuration" }