CLI: Allow running class files with '.class' extension in 'kotlin' script
Catch NoClassDefFoundError and print message with cause. #KT-11164 Fixed #KT-46171 Fixed
This commit is contained in:
committed by
Alexander Udalov
parent
b7d88be41a
commit
b24c3a106e
@@ -144,7 +144,19 @@ object Main {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setRunner(MainClassRunner(arg))
|
val workingDir = File(".")
|
||||||
|
val classFile = File(arg)
|
||||||
|
|
||||||
|
// Allow running class files with '.class' extension.
|
||||||
|
// In order to infer its fully qualified name, it should be located in the current working directory or a subdirectory of it
|
||||||
|
val className =
|
||||||
|
if (arg.endsWith(".class") && classFile.exists() && classFile.canonicalPath.contains(workingDir.canonicalPath)) {
|
||||||
|
classFile.canonicalFile.toRelativeString(workingDir.canonicalFile)
|
||||||
|
.removeSuffix(".class")
|
||||||
|
.replace(File.separatorChar, '.')
|
||||||
|
} else arg
|
||||||
|
|
||||||
|
setRunner(MainClassRunner(className))
|
||||||
restAsArguments()
|
restAsArguments()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import java.net.URLClassLoader
|
|||||||
import java.util.jar.Attributes
|
import java.util.jar.Attributes
|
||||||
import java.util.jar.JarFile
|
import java.util.jar.JarFile
|
||||||
|
|
||||||
class RunnerException(message: String) : RuntimeException(message)
|
class RunnerException(message: String, cause: Throwable? = null) : RuntimeException(message, cause)
|
||||||
|
|
||||||
abstract class AbstractRunner : Runner {
|
abstract class AbstractRunner : Runner {
|
||||||
protected abstract val className: String
|
protected abstract val className: String
|
||||||
@@ -40,6 +40,12 @@ abstract class AbstractRunner : Runner {
|
|||||||
}
|
}
|
||||||
catch (e: ClassNotFoundException) {
|
catch (e: ClassNotFoundException) {
|
||||||
throw RunnerException("could not find or load main class $className")
|
throw RunnerException("could not find or load main class $className")
|
||||||
|
} catch (e: NoClassDefFoundError) {
|
||||||
|
val message = """
|
||||||
|
could not find or load main class $className
|
||||||
|
Caused by: $e
|
||||||
|
""".trimIndent()
|
||||||
|
throw RunnerException(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
val main = try {
|
val main = try {
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fun main() {
|
||||||
|
print("ok")
|
||||||
|
}
|
||||||
@@ -354,4 +354,104 @@ compiler/testData/launcher/noInline.myscript:1:7: error: unresolved reference: C
|
|||||||
expectedExitCode = 1
|
expectedExitCode = 1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testNoClassDefFoundErrorWhenClassInDefaultPackage() {
|
||||||
|
val testDir = File("$tmpdir/test")
|
||||||
|
|
||||||
|
runProcess("kotlinc", "$testDataDirectory/defaultPackage.kt", "-d", testDir.path)
|
||||||
|
assertExists(File("${testDir.path}/DefaultPackageKt.class"))
|
||||||
|
|
||||||
|
runProcess(
|
||||||
|
"kotlin", "test.DefaultPackageKt", workDirectory = tmpdir, expectedExitCode = 1,
|
||||||
|
expectedStderr = """
|
||||||
|
error: could not find or load main class test.DefaultPackageKt
|
||||||
|
Caused by: java.lang.NoClassDefFoundError: test/DefaultPackageKt (wrong name: DefaultPackageKt)
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNoClassDefFoundErrorWhenClassNotInDefaultPackage() {
|
||||||
|
val testDir = File("$tmpdir/test")
|
||||||
|
|
||||||
|
runProcess("kotlinc", "$testDataDirectory/helloWorld.kt", "-d", tmpdir.path)
|
||||||
|
assertExists(File("${testDir.path}/HelloWorldKt.class"))
|
||||||
|
|
||||||
|
runProcess(
|
||||||
|
"kotlin", "HelloWorldKt", workDirectory = testDir, expectedExitCode = 1,
|
||||||
|
expectedStderr = """
|
||||||
|
error: could not find or load main class HelloWorldKt
|
||||||
|
Caused by: java.lang.NoClassDefFoundError: HelloWorldKt (wrong name: test/HelloWorldKt)
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class whose full qualified name is `DefaultPackageKt` and is located in path `$tmpdir/test/DefaultPackageKt.class`
|
||||||
|
*/
|
||||||
|
fun testRunClassFileWithExtensionInDefaultPackage() {
|
||||||
|
val subDir = File("$tmpdir/test/sub").apply { mkdirs() }
|
||||||
|
val testDir = File("$tmpdir/test")
|
||||||
|
|
||||||
|
runProcess("kotlinc", "$testDataDirectory/defaultPackage.kt", "-d", testDir.path)
|
||||||
|
assertExists(File("${testDir.path}/DefaultPackageKt.class"))
|
||||||
|
|
||||||
|
runProcess(
|
||||||
|
"kotlin", "test/DefaultPackageKt.class", workDirectory = tmpdir, expectedExitCode = 1,
|
||||||
|
expectedStderr = """
|
||||||
|
error: could not find or load main class test.DefaultPackageKt
|
||||||
|
Caused by: java.lang.NoClassDefFoundError: test/DefaultPackageKt (wrong name: DefaultPackageKt)
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
runProcess("kotlin", "DefaultPackageKt.class", expectedStdout = "ok", workDirectory = testDir)
|
||||||
|
runProcess("kotlin", "./sub/../DefaultPackageKt.class", expectedStdout = "ok", workDirectory = testDir)
|
||||||
|
runProcess(
|
||||||
|
"kotlin", "../DefaultPackageKt.class", expectedExitCode = 1,
|
||||||
|
expectedStderr = "error: could not find or load main class ../DefaultPackageKt.class\n",
|
||||||
|
workDirectory = subDir
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class whose full qualified name is `test.HelloWorldKt` and is located in path `$tmpdir/test/HelloWorldKt.class`
|
||||||
|
*/
|
||||||
|
fun testRunClassFileWithExtensionNotInDefaultPackage() {
|
||||||
|
val subDir = File("$tmpdir/test/sub").apply { mkdirs() }
|
||||||
|
val testDir = File("$tmpdir/test")
|
||||||
|
|
||||||
|
runProcess("kotlinc", "$testDataDirectory/helloWorld.kt", "-d", tmpdir.path)
|
||||||
|
assertExists(File("${testDir.path}/HelloWorldKt.class"))
|
||||||
|
|
||||||
|
runProcess("kotlin", "test/HelloWorldKt.class", expectedStdout = "Hello!\n", workDirectory = tmpdir)
|
||||||
|
runProcess(
|
||||||
|
"kotlin", "test.HelloWorldKt.class", expectedExitCode = 1,
|
||||||
|
expectedStderr = "error: could not find or load main class test.HelloWorldKt.class\n",
|
||||||
|
workDirectory = tmpdir
|
||||||
|
)
|
||||||
|
runProcess("kotlin", "test/sub/../../test/HelloWorldKt.class", expectedStdout = "Hello!\n", workDirectory = tmpdir)
|
||||||
|
runProcess(
|
||||||
|
"kotlin", "./HelloWorldKt.class", workDirectory = testDir, expectedExitCode = 1,
|
||||||
|
expectedStderr = """
|
||||||
|
error: could not find or load main class HelloWorldKt
|
||||||
|
Caused by: java.lang.NoClassDefFoundError: HelloWorldKt (wrong name: test/HelloWorldKt)
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
runProcess(
|
||||||
|
"kotlin", "HelloWorldKt.class", workDirectory = testDir, expectedExitCode = 1,
|
||||||
|
expectedStderr = """
|
||||||
|
error: could not find or load main class HelloWorldKt
|
||||||
|
Caused by: java.lang.NoClassDefFoundError: HelloWorldKt (wrong name: test/HelloWorldKt)
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
runProcess(
|
||||||
|
"kotlin", "../HelloWorldKt.class", expectedExitCode = 1,
|
||||||
|
expectedStderr = "error: could not find or load main class ../HelloWorldKt.class\n",
|
||||||
|
workDirectory = subDir
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user