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
+1
View File
@@ -750,6 +750,7 @@
<arg value="${toString:classpath.path}"/>
<arg value="-module-name"/>
<arg value="@{moduleName}"/>
<arg value="-Xallow-kotlin-package"/>
</java>
<javac2 srcdir="${toString:src.dirset}" destdir="@{output}" debug="true" debuglevel="lines,vars,source"
@@ -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" }
+1
View File
@@ -5,6 +5,7 @@ where advanced options include:
-Xno-optimize Disable optimizations
-Xreport-perf Report detailed performance statistics
-Xmultifile-facades-open Compile multifile facade classes as open
-Xallow-kotlin-package Allow compiling code in package 'kotlin'
-Xno-inline Disable method inlining
-Xrepeat <count> Repeat compilation (for performance analysis)
-Xplugin <path> Load plugins from the given classpath
+3
View File
@@ -0,0 +1,3 @@
$TESTDATA_DIR$/kotlinPackage.kt
-d
$TEMP_DIR$
+4
View File
@@ -0,0 +1,4 @@
package kotlin.mylibrary
class MyLibraryManager {
}
+4
View File
@@ -0,0 +1,4 @@
compiler/testData/cli/jvm/kotlinPackage.kt:1:1: error: only the Kotlin standard library is allowed to use the 'kotlin' package
package kotlin.mylibrary
^
COMPILATION_ERROR
@@ -133,6 +133,12 @@ public class KotlincExecutableTestGenerated extends AbstractKotlincExecutableTes
doJvmTest(fileName);
}
@TestMetadata("kotlinPackage.args")
public void testKotlinPackage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/kotlinPackage.args");
doJvmTest(fileName);
}
@TestMetadata("multipleTextRangesInDiagnosticsOrder.args")
public void testMultipleTextRangesInDiagnosticsOrder() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/multipleTextRangesInDiagnosticsOrder.args");
+1
View File
@@ -40,6 +40,7 @@
<configuration>
<args>
<arg>-Xmultifile-facades-open</arg>
<arg>-Xallow-kotlin-package</arg>
</args>
</configuration>