Move importsDumper to compiler plugin
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
|
||||
description = "Extension for saving imports of .kt-files in JSON"
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
val kotlinxSerializationVersion = "0.4.2"
|
||||
|
||||
dependencies {
|
||||
compile(project(":compiler:frontend.java"))
|
||||
compile(project(":compiler:plugin-api"))
|
||||
compileOnly("org.jetbrains.kotlinx", "kotlinx-serialization-runtime", kotlinxSerializationVersion) { isTransitive = false }
|
||||
|
||||
compile(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
|
||||
testCompile(project(":compiler:tests-common"))
|
||||
testCompile(projectTests(":compiler:tests-common"))
|
||||
|
||||
|
||||
embeddedComponents("org.jetbrains.kotlinx", "kotlinx-serialization-runtime", kotlinxSerializationVersion) { isTransitive = false }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { projectDefault() }
|
||||
}
|
||||
|
||||
projectTest {
|
||||
workingDir = rootDir
|
||||
dependsOn(":dist")
|
||||
}
|
||||
|
||||
runtimeJar {
|
||||
fromEmbeddedComponents()
|
||||
}
|
||||
|
||||
dist()
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
# that can be found in the license/LICENSE.txt file.
|
||||
#
|
||||
|
||||
org.jetbrains.kotlin.importsDumper.ImportsDumperCommandLineProcessor
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
# that can be found in the license/LICENSE.txt file.
|
||||
#
|
||||
|
||||
org.jetbrains.kotlin.importsDumper.ImportsDumperComponentRegistrar
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.importsDumper
|
||||
|
||||
import org.jetbrains.kotlin.compiler.plugin.CliOption
|
||||
import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
|
||||
import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
||||
|
||||
object ImportsDumperCliOptions {
|
||||
val DESTINATION = CliOption(
|
||||
name = "output-imports",
|
||||
valueDescription = "<path>",
|
||||
description = "Output imports from all compiled files to the specified file in JSON format",
|
||||
required = false // non-required because importsDumper is a bundled plugin
|
||||
)
|
||||
}
|
||||
|
||||
object ImportsDumperConfigurationKeys {
|
||||
val DESTINATION = CompilerConfigurationKey.create<String>("Destination of imports dump")
|
||||
}
|
||||
|
||||
class ImportsDumperCommandLineProcessor : CommandLineProcessor {
|
||||
override val pluginId: String = PLUGIN_ID
|
||||
|
||||
override val pluginOptions: Collection<CliOption> = listOf(ImportsDumperCliOptions.DESTINATION)
|
||||
|
||||
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
|
||||
when (option) {
|
||||
ImportsDumperCliOptions.DESTINATION -> configuration.put(ImportsDumperConfigurationKeys.DESTINATION, value)
|
||||
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PLUGIN_ID = "org.jetbrains.kotlin.importsDumper"
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.importsDumper
|
||||
|
||||
import com.intellij.mock.MockProject
|
||||
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||
|
||||
class ImportsDumperComponentRegistrar : ComponentRegistrar {
|
||||
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
||||
val destinationPath = configuration[ImportsDumperConfigurationKeys.DESTINATION] ?: return
|
||||
AnalysisHandlerExtension.registerExtension(project, ImportsDumperExtension(destinationPath))
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.importsDumper
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import kotlinx.serialization.internal.StringSerializer
|
||||
import kotlinx.serialization.json.JSON
|
||||
import kotlinx.serialization.list
|
||||
import kotlinx.serialization.map
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.container.ComponentProvider
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||
import java.io.File
|
||||
|
||||
class ImportsDumperExtension(destinationPath: String) : AnalysisHandlerExtension {
|
||||
private val destination: File = File(destinationPath)
|
||||
|
||||
override fun doAnalysis(
|
||||
project: Project,
|
||||
module: ModuleDescriptor,
|
||||
projectContext: ProjectContext,
|
||||
files: Collection<KtFile>,
|
||||
bindingTrace: BindingTrace,
|
||||
componentProvider: ComponentProvider
|
||||
): AnalysisResult? {
|
||||
val filePathToImports: MutableMap<String, List<String>> = mutableMapOf()
|
||||
|
||||
for (file in files) {
|
||||
filePathToImports[file.virtualFilePath] = file.importDirectives.map { it.text }
|
||||
}
|
||||
|
||||
val serializer = (StringSerializer to StringSerializer.list).map
|
||||
|
||||
val jsonStringWithImports = JSON.stringify(serializer, filePathToImports)
|
||||
|
||||
destination.writeText(jsonStringWithImports)
|
||||
|
||||
return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package a
|
||||
|
||||
import c.JavaC
|
||||
|
||||
class A1 {
|
||||
val j: JavaC = JavaC()
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package a
|
||||
|
||||
class A2 {
|
||||
val a1: A1? = null
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package b
|
||||
|
||||
import a.*
|
||||
|
||||
class B1 {
|
||||
companion object {
|
||||
val a1: A1 = A1()
|
||||
val a2: A2 = A2()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package b.nestedB
|
||||
|
||||
import a.A1 as AliasedA1
|
||||
import a.A1
|
||||
|
||||
fun foo(x: AliasedA1): Int = TODO()
|
||||
fun bar(x: A1): Int = TODO()
|
||||
@@ -0,0 +1,16 @@
|
||||
package c
|
||||
|
||||
import a.A1
|
||||
import a.A2
|
||||
import b.B1.Companion.a2
|
||||
import b.nestedB.bar
|
||||
import b.nestedB.foo
|
||||
|
||||
class C1 {
|
||||
val x = foo(TODO())
|
||||
val y = bar(TODO())
|
||||
|
||||
val z: A1? = null
|
||||
val t: A2? = a2
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package c;
|
||||
|
||||
import a.A1;
|
||||
import b.B1;
|
||||
import b.nestedB.B2Kt;
|
||||
|
||||
public class JavaC {
|
||||
private void doStuff() {
|
||||
C1 c1 = new C1();
|
||||
B1 b1 = new B1();
|
||||
B2Kt.bar(new A1());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"$TESTDATA_DIR$\/a\/A1.kt":["import c.JavaC"],"$TESTDATA_DIR$\/a\/A2.kt":[],"$TESTDATA_DIR$\/b\/B1.kt":["import a.*"],"$TESTDATA_DIR$\/b\/nestedB\/B2.kt":["import a.A1 as AliasedA1","import a.A1"],"$TESTDATA_DIR$\/c\/C1.kt":["import a.A1","import a.A2","import b.B1.Companion.a2","import b.nestedB.bar","import b.nestedB.foo"]}
|
||||
@@ -0,0 +1 @@
|
||||
OK
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.importsDumper
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.testFramework.TestDataPath
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.cli.AbstractCliTest.*
|
||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
|
||||
import org.jetbrains.kotlin.test.TestMetadata
|
||||
import java.io.File
|
||||
|
||||
@TestMetadata("plugins/imports-dumper/testData")
|
||||
@TestDataPath("\$PROJECT_ROOT")
|
||||
class ImportsDumperTest : TestCaseWithTmpdir() {
|
||||
|
||||
fun testSimple() {
|
||||
doTest("plugins/imports-dumper/testData/simpleCase")
|
||||
}
|
||||
|
||||
private fun doTest(testDataDirPath: String) {
|
||||
System.setProperty("java.awt.headless", "true")
|
||||
val testDataDir = File(testDataDirPath)
|
||||
val expectedDumpFile = testDataDir.resolve(testDataDir.name + ".dump")
|
||||
val expectedOutputFile = testDataDir.resolve(testDataDir.name + ".out")
|
||||
val actualDumpFile = tmpdir.resolve(testDataDir.name + ".dump")
|
||||
|
||||
// Check CLI-output of compiler
|
||||
val actualOutput = invokeImportsDumperAndGrabOutput(testDataDir, tmpdir, actualDumpFile)
|
||||
KotlinTestUtils.assertEqualsToFile(expectedOutputFile, actualOutput)
|
||||
|
||||
// Check imports dump
|
||||
// Note that imports dumper outputs absolute paths to files, which is inconvenient for tests,
|
||||
// so we have to relativize them
|
||||
val actualRelativizedDump = FileUtil.loadFile(actualDumpFile, Charsets.UTF_8.name(), /* convertLineSeparators = */ true)
|
||||
.relativizeAbsolutePaths(testDataDir)
|
||||
|
||||
KotlinTestUtils.assertEqualsToFile(expectedDumpFile, actualRelativizedDump)
|
||||
}
|
||||
|
||||
private fun invokeImportsDumperAndGrabOutput(testDataDir: File, tmpDir: File, actualDumpFile: File): String {
|
||||
val importsDumperJarInDist = File("dist/kotlinc/lib/kotlin-imports-dumper-compiler-plugin.jar")
|
||||
if (!importsDumperJarInDist.exists()) {
|
||||
TestCase.fail(".jar for imports dumper isn't found, searched: ${importsDumperJarInDist.absolutePath}")
|
||||
}
|
||||
|
||||
val compiler = K2JVMCompiler()
|
||||
val (output, exitCode) = executeCompilerGrabOutput(
|
||||
compiler,
|
||||
listOf(
|
||||
testDataDir.absolutePath,
|
||||
"-d",
|
||||
tmpDir.path,
|
||||
"-Xplugin=${importsDumperJarInDist.path}",
|
||||
"-P",
|
||||
"plugin:${ImportsDumperCommandLineProcessor.PLUGIN_ID}:${ImportsDumperCliOptions.DESTINATION.name}=${actualDumpFile.path}"
|
||||
)
|
||||
)
|
||||
|
||||
return getNormalizedCompilerOutput(output, exitCode, testDataDir.path)
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.relativizeAbsolutePaths(relativeTo: File): String {
|
||||
// JSON escapes slashes
|
||||
val pattern = relativeTo.absoluteFile.toString().replace("/", "\\/")
|
||||
return this.replace(pattern, "\$TESTDATA_DIR$")
|
||||
}
|
||||
Reference in New Issue
Block a user