diff --git a/.idea/artifacts/KotlinPlugin.xml b/.idea/artifacts/KotlinPlugin.xml
index f6d23649e60..91e7055017f 100644
--- a/.idea/artifacts/KotlinPlugin.xml
+++ b/.idea/artifacts/KotlinPlugin.xml
@@ -1,90 +1,97 @@
-
- $PROJECT_DIR$/out/artifacts/Kotlin
-
-
- file://$PROJECT_DIR$/idea-runner/runner.xml
- copy-runtime-for-idea-plugin
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ $PROJECT_DIR$/out/artifacts/Kotlin
+
+
+ file://$PROJECT_DIR$/idea-runner/runner.xml
+ copy-runtime-for-idea-plugin
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 27f12a3cb19..b0a44652e07 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -3,13 +3,15 @@
-
+
+
+
diff --git a/build.xml b/build.xml
index 427843676c3..45071f459ee 100644
--- a/build.xml
+++ b/build.xml
@@ -828,7 +828,7 @@
-
+
@@ -839,7 +839,7 @@
-
+
diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPaths.java b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPaths.java
index 462a2f130dd..787c6c8ad21 100644
--- a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPaths.java
+++ b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPaths.java
@@ -48,6 +48,9 @@ public interface KotlinPaths {
@NotNull
File getJsStdLibSrcJarPath();
+ @NotNull
+ File getAllOpenPluginJarPath();
+
@NotNull
File getCompilerPath();
diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPathsFromHomeDir.java b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPathsFromHomeDir.java
index cb6adbc0e75..afd05e5ebe6 100644
--- a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPathsFromHomeDir.java
+++ b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPathsFromHomeDir.java
@@ -82,6 +82,12 @@ public class KotlinPathsFromHomeDir implements KotlinPaths {
return getLibraryFile(PathUtil.JS_LIB_SRC_JAR_NAME);
}
+ @NotNull
+ @Override
+ public File getAllOpenPluginJarPath() {
+ return getLibraryFile(PathUtil.ALLOPEN_PLUGIN_JAR_NAME);
+ }
+
@NotNull
@Override
public File getCompilerPath() {
diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.java b/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.java
index 8e2469f166b..3bce0e86d01 100644
--- a/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.java
+++ b/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.java
@@ -29,6 +29,7 @@ public class PathUtil {
public static final String JPS_KOTLIN_HOME_PROPERTY = "jps.kotlin.home";
public static final String JS_LIB_JAR_NAME = "kotlin-jslib.jar";
+ public static final String ALLOPEN_PLUGIN_JAR_NAME = "allopen-compiler-plugin.jar";
public static final String JS_LIB_SRC_JAR_NAME = "kotlin-jslib-sources.jar";
public static final String KOTLIN_JAVA_RUNTIME_JAR = "kotlin-runtime.jar";
public static final String KOTLIN_JAVA_REFLECT_JAR = "kotlin-reflect.jar";
diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt
index 3bb8ce6112c..9c8de1e3c6b 100755
--- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt
+++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt
@@ -1159,7 +1159,7 @@ fun main(args: Array) {
}
}
- testGroup("plugins/plugins-tests/tests", "plugins/allopen/testData") {
+ testGroup("plugins/plugins-tests/tests", "plugins/allopen/allopen-cli/testData") {
testClass() {
model("bytecodeListing", extension = "kt")
}
diff --git a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt
index d6a249abf64..6fdc2cb05c9 100644
--- a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt
+++ b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt
@@ -33,21 +33,31 @@ import org.jetbrains.idea.maven.model.MavenPlugin
import org.jetbrains.idea.maven.project.*
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
-import org.jetbrains.kotlin.config.LanguageVersion
-import org.jetbrains.kotlin.config.TargetPlatformKind
+import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
+import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.facet.configureFacet
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
-import org.jetbrains.kotlin.idea.facet.initializeIfNeeded
-import org.jetbrains.kotlin.idea.facet.mavenLibraryId
import org.jetbrains.kotlin.idea.maven.configuration.KotlinMavenConfigurator
import java.io.File
import java.util.*
-private val KotlinPluginGroupId = "org.jetbrains.kotlin"
-private val KotlinPluginArtifactId = "kotlin-maven-plugin"
-private val KotlinPluginSourceDirsConfig = "sourceDirs"
+interface MavenProjectImportHandler {
+ companion object : ProjectExtensionDescriptor(
+ "org.jetbrains.kotlin.mavenProjectImportHandler",
+ MavenProjectImportHandler::class.java
+ )
+
+ operator fun invoke(facet: KotlinFacet, mavenProject: MavenProject)
+}
+
+class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_ARTIFACT_ID) {
+ companion object {
+ val KOTLIN_PLUGIN_GROUP_ID = "org.jetbrains.kotlin"
+ val KOTLIN_PLUGIN_ARTIFACT_ID = "kotlin-maven-plugin"
+
+ val KOTLIN_PLUGIN_SOURCE_DIRS_CONFIG = "sourceDirs"
+ }
-class KotlinMavenImporter : MavenImporter(KotlinPluginGroupId, KotlinPluginArtifactId) {
override fun preProcess(module: Module, mavenProject: MavenProject, changes: MavenProjectChanges, modifiableModelsProvider: IdeModifiableModelsProvider) {
}
@@ -70,7 +80,7 @@ class KotlinMavenImporter : MavenImporter(KotlinPluginGroupId, KotlinPluginArtif
if (changes.dependencies) {
// TODO: here we have to process all kotlin libraries but for now we only handle standard libraries
- val artifacts = mavenProject.dependencyArtifactIndex.data[KotlinPluginGroupId]?.values?.flatMap { it.filter { it.isResolved } } ?: emptyList()
+ val artifacts = mavenProject.dependencyArtifactIndex.data[KOTLIN_PLUGIN_GROUP_ID]?.values?.flatMap { it.filter { it.isResolved } } ?: emptyList()
val librariesWithNoSources = ArrayList()
OrderEnumerator.orderEntries(module).forEachLibrary { library ->
@@ -93,7 +103,9 @@ class KotlinMavenImporter : MavenImporter(KotlinPluginGroupId, KotlinPluginArtif
private fun configureFacet(mavenProject: MavenProject, modifiableModelsProvider: IdeModifiableModelsProvider, module: Module) {
val compilerVersion = mavenProject.findPlugin(KotlinMavenConfigurator.GROUP_ID, KotlinMavenConfigurator.MAVEN_PLUGIN_ID)?.version
?: return
- module.getOrCreateFacet(modifiableModelsProvider).configureFacet(compilerVersion, modifiableModelsProvider)
+ val kotlinFacet = module.getOrCreateFacet(modifiableModelsProvider)
+ kotlinFacet.configureFacet(compilerVersion, modifiableModelsProvider)
+ MavenProjectImportHandler.getInstances(module.project).forEach { it(kotlinFacet, mavenProject) }
}
// TODO in theory it should work like this but it doesn't as it couldn't unmark source roots that are not roots anymore.
@@ -143,8 +155,8 @@ class KotlinMavenImporter : MavenImporter(KotlinPluginGroupId, KotlinPluginArtif
}.distinct()
}
-private fun MavenPlugin.isKotlinPlugin() = groupId == KotlinPluginGroupId && artifactId == KotlinPluginArtifactId
-private fun Element?.sourceDirectories(): List = this?.getChildren(KotlinPluginSourceDirsConfig)?.flatMap { it.children ?: emptyList() }?.map { it.textTrim } ?: emptyList()
+private fun MavenPlugin.isKotlinPlugin() = groupId == KotlinMavenImporter.KOTLIN_PLUGIN_GROUP_ID && artifactId == KotlinMavenImporter.KOTLIN_PLUGIN_ARTIFACT_ID
+private fun Element?.sourceDirectories(): List = this?.getChildren(KotlinMavenImporter.KOTLIN_PLUGIN_SOURCE_DIRS_CONFIG)?.flatMap { it.children ?: emptyList() }?.map { it.textTrim } ?: emptyList()
private fun MavenPlugin.Execution.sourceType() =
goals.map { if (isTestGoalName(it)) SourceType.TEST else SourceType.PROD }
.distinct()
diff --git a/idea/src/META-INF/extensions/ide.xml b/idea/src/META-INF/extensions/ide.xml
index 6d1698ca399..228c42d5e73 100644
--- a/idea/src/META-INF/extensions/ide.xml
+++ b/idea/src/META-INF/extensions/ide.xml
@@ -2,6 +2,10 @@
+
+
diff --git a/idea/src/META-INF/gradle.xml b/idea/src/META-INF/gradle.xml
index e3d118e272f..aedc0407b42 100644
--- a/idea/src/META-INF/gradle.xml
+++ b/idea/src/META-INF/gradle.xml
@@ -1,13 +1,14 @@
-
-
-
-
-
+
+
+
+
+
@@ -19,9 +20,7 @@
language="Groovy"
hasStaticDescription="true"
level="WARNING"/>
-
-
+
+
+
+
+
+
diff --git a/idea/src/META-INF/maven.xml b/idea/src/META-INF/maven.xml
index 3d38512ed1f..09f2d439b63 100644
--- a/idea/src/META-INF/maven.xml
+++ b/idea/src/META-INF/maven.xml
@@ -2,9 +2,10 @@
-
+
+
@@ -21,6 +22,12 @@
+
+
+
+
+
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectDataService.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectDataService.kt
index c8bdbd16100..66fa8116ed4 100644
--- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectDataService.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectDataService.kt
@@ -23,6 +23,8 @@ import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsPr
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.project.Project
+import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
+import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.facet.configureFacet
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
import org.jetbrains.kotlin.idea.inspections.gradle.findAll
@@ -30,6 +32,15 @@ import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
+interface GradleProjectImportHandler {
+ companion object : ProjectExtensionDescriptor(
+ "org.jetbrains.kotlin.gradleProjectImportHandler",
+ GradleProjectImportHandler::class.java
+ )
+
+ operator fun invoke(facet: KotlinFacet, sourceSetNode: DataNode)
+}
+
class KotlinGradleProjectDataService : AbstractProjectDataService() {
override fun getTargetDataKey() = GradleSourceSetData.KEY
@@ -47,7 +58,9 @@ class KotlinGradleProjectDataService : AbstractProjectDataService
+private val KOTLIN_PLUGIN_PATH_MARKER = "${KotlinWithGradleConfigurator.GROUP_ID}/${KotlinWithGradleConfigurator.GRADLE_PLUGIN_ID}/"
+
+// Maven local repo path (example): ~/.m2/repository/org/jetbrains/kotlin/kotlin-runtime/
+private val KOTLIN_PLUGIN_PATH_MARKER_FOR_MAVEN_LOCAL_REPO =
+ "${KotlinWithGradleConfigurator.GROUP_ID.replace('.', '/')}/${KotlinWithGradleConfigurator.GRADLE_PLUGIN_ID}/"
+
internal fun findKotlinPluginVersion(classpathData: BuildScriptClasspathData): String? {
for (classPathEntry in classpathData.classpathEntries) {
for (path in classPathEntry.classesFile) {
val uniformedPath = path.replace('\\', '/')
+ // check / for local maven repo, and '.' for gradle
if (uniformedPath.contains(KOTLIN_PLUGIN_PATH_MARKER)) {
val versionSubstring = uniformedPath.substringAfter(KOTLIN_PLUGIN_PATH_MARKER).substringBefore('/', "")
if (versionSubstring != "") {
- return versionSubstring;
+ return versionSubstring
+ }
+ } else if (uniformedPath.contains(KOTLIN_PLUGIN_PATH_MARKER_FOR_MAVEN_LOCAL_REPO)) {
+ val versionSubstring = uniformedPath.substringAfter(KOTLIN_PLUGIN_PATH_MARKER_FOR_MAVEN_LOCAL_REPO).substringBefore('/', "")
+ if (versionSubstring != "") {
+ return versionSubstring
}
}
}
diff --git a/libraries/tools/kotlin-allopen/pom.xml b/libraries/tools/kotlin-allopen/pom.xml
index 79702108e65..d6d980393fd 100755
--- a/libraries/tools/kotlin-allopen/pom.xml
+++ b/libraries/tools/kotlin-allopen/pom.xml
@@ -6,7 +6,7 @@
4.0.0
3.0.4
- ${basedir}/../../../plugins/allopen/src
+ ${basedir}/../../../plugins/allopen/allopen-cli/src
${basedir}/src/main/kotlin
${basedir}/src/main/resources
${basedir}/target/src/main/kotlin
diff --git a/libraries/tools/kotlin-allopen/src/main/kotlin/org/jetbrains/kotlin/allopen/gradle/AllOpenSubplugin.kt b/libraries/tools/kotlin-allopen/src/main/kotlin/org/jetbrains/kotlin/allopen/gradle/AllOpenSubplugin.kt
index ab91c24af24..e361a903054 100644
--- a/libraries/tools/kotlin-allopen/src/main/kotlin/org/jetbrains/kotlin/allopen/gradle/AllOpenSubplugin.kt
+++ b/libraries/tools/kotlin-allopen/src/main/kotlin/org/jetbrains/kotlin/allopen/gradle/AllOpenSubplugin.kt
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.allopen.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
+import org.gradle.api.artifacts.ResolvedArtifact
+import org.gradle.api.internal.AbstractTask
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.compile.AbstractCompile
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
@@ -32,14 +34,39 @@ class AllOpenGradleSubplugin : Plugin {
}
}
+ fun Project.getBuildscriptArtifacts(): Set =
+ buildscript.configurations.findByName("classpath")?.resolvedConfiguration?.resolvedArtifacts ?: emptySet()
+
override fun apply(project: Project) {
- project.extensions.create("allOpen", AllOpenExtension::class.java)
+ val allOpenExtension = project.extensions.create("allOpen", AllOpenExtension::class.java)
+
+ project.afterEvaluate {
+ val fqNamesAsString = allOpenExtension.myAnnotations.joinToString(",")
+ project.extensions.extraProperties.set("kotlinAllOpenAnnotations", fqNamesAsString)
+
+ val allBuildscriptArtifacts = project.getBuildscriptArtifacts() + project.rootProject.getBuildscriptArtifacts()
+ val allOpenCompilerPluginFile = allBuildscriptArtifacts.filter {
+ val id = it.moduleVersion.id
+ id.group == AllOpenKotlinGradleSubplugin.ALLOPEN_GROUP_NAME
+ && id.name == AllOpenKotlinGradleSubplugin.ALLOPEN_ARTIFACT_NAME
+ }.firstOrNull()?.file?.absolutePath ?: ""
+
+ open class TaskForAllOpen : AbstractTask()
+ project.tasks.add(project.tasks.create("allOpenDataStorageTask", TaskForAllOpen::class.java).apply {
+ isEnabled = false
+ description = "Supported annotations: " + fqNamesAsString +
+ "; Compiler plugin classpath: $allOpenCompilerPluginFile"
+ })
+ }
}
}
class AllOpenKotlinGradleSubplugin : KotlinGradleSubplugin {
- private companion object {
- val ANNOTATIONS_ARG_NAME = "annotation"
+ companion object {
+ val ALLOPEN_GROUP_NAME = "org.jetbrains.kotlin"
+ val ALLOPEN_ARTIFACT_NAME = "kotlin-allopen"
+
+ private val ANNOTATIONS_ARG_NAME = "annotation"
}
override fun isApplicable(project: Project, task: AbstractCompile) = AllOpenGradleSubplugin.isEnabled(project)
@@ -64,7 +91,7 @@ class AllOpenKotlinGradleSubplugin : KotlinGradleSubplugin {
return options
}
- override fun getArtifactName() = "kotlin-allopen"
- override fun getGroupName() = "org.jetbrains.kotlin"
- override fun getPluginName() = "org.jetbrains.kotlin.allopen"
+ override fun getGroupName() = ALLOPEN_GROUP_NAME
+ override fun getArtifactName() = ALLOPEN_ARTIFACT_NAME
+ override fun getCompilerPluginId() = "org.jetbrains.kotlin.allopen"
}
\ No newline at end of file
diff --git a/plugins/allopen/allopen.iml b/plugins/allopen/allopen-cli/allopen-cli.iml
similarity index 100%
rename from plugins/allopen/allopen.iml
rename to plugins/allopen/allopen-cli/allopen-cli.iml
diff --git a/plugins/allopen/src/AllOpenDeclarationAttributeAltererExtension.kt b/plugins/allopen/allopen-cli/src/AllOpenDeclarationAttributeAltererExtension.kt
similarity index 64%
rename from plugins/allopen/src/AllOpenDeclarationAttributeAltererExtension.kt
rename to plugins/allopen/allopen-cli/src/AllOpenDeclarationAttributeAltererExtension.kt
index fc91915c3ff..1c19c5ccfc2 100644
--- a/plugins/allopen/src/AllOpenDeclarationAttributeAltererExtension.kt
+++ b/plugins/allopen/allopen-cli/src/AllOpenDeclarationAttributeAltererExtension.kt
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.allopen
import org.jetbrains.kotlin.descriptors.ClassDescriptor
-import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
@@ -28,10 +27,14 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.TypeUtils
-class AllOpenDeclarationAttributeAltererExtension(val allOpenAnnotationFqNames: List) : DeclarationAttributeAltererExtension {
- private companion object {
- private val INHERITED_FQNAME = "java.lang.annotation.Inherited"
- }
+class CliAllOpenDeclarationAttributeAltererExtension(
+ private val allOpenAnnotationFqNames: List
+) : AbstractAllOpenDeclarationAttributeAltererExtension() {
+ override fun getAllOpenAnnotationFqNames(modifierListOwner: KtModifierListOwner) = allOpenAnnotationFqNames
+}
+
+abstract class AbstractAllOpenDeclarationAttributeAltererExtension : DeclarationAttributeAltererExtension {
+ abstract fun getAllOpenAnnotationFqNames(modifierListOwner: KtModifierListOwner): List
override fun refineDeclarationModality(
modifierListOwner: KtModifierListOwner,
@@ -40,10 +43,8 @@ class AllOpenDeclarationAttributeAltererExtension(val allOpenAnnotationFqNames:
currentModality: Modality,
bindingContext: BindingContext
): Modality? {
- // We alter only 'final' modality
- when (currentModality) {
- Modality.OPEN, Modality.ABSTRACT, Modality.SEALED -> return null
- else -> {}
+ if (currentModality != Modality.FINAL) {
+ return null
}
// Explicit final
@@ -52,31 +53,34 @@ class AllOpenDeclarationAttributeAltererExtension(val allOpenAnnotationFqNames:
}
val descriptor = declaration ?: containingDeclaration ?: return null
- if (descriptor.hasAllOpenAnnotation()) return Modality.OPEN
+ if (descriptor.hasAllOpenAnnotation(modifierListOwner)) return Modality.OPEN
return null
}
- private fun DeclarationDescriptor.hasAllOpenAnnotation(): Boolean {
- if (annotations.any { it.isAllOpenAnnotation() }) return true
+ private fun DeclarationDescriptor.hasAllOpenAnnotation(modifierListOwner: KtModifierListOwner): Boolean {
+ if (annotations.any { it.isAllOpenAnnotation(modifierListOwner) }) return true
if (this is ClassDescriptor) {
for (superType in TypeUtils.getAllSupertypes(defaultType)) {
val superTypeDescriptor = superType.constructor.declarationDescriptor as? ClassDescriptor ?: continue
- if (superTypeDescriptor.annotations.any { it.isAllOpenAnnotation() }) return true
+ if (superTypeDescriptor.annotations.any { it.isAllOpenAnnotation(modifierListOwner) }) return true
}
}
return false
}
- private fun AnnotationDescriptor.isAllOpenAnnotation(allowMetaAnnotations: Boolean = true): Boolean {
+ private fun AnnotationDescriptor.isAllOpenAnnotation(
+ modifierListOwner: KtModifierListOwner,
+ allowMetaAnnotations: Boolean = true
+ ): Boolean {
val annotationType = type.constructor.declarationDescriptor ?: return false
- if (annotationType.fqNameSafe.asString() in allOpenAnnotationFqNames) return true
+ if (annotationType.fqNameSafe.asString() in getAllOpenAnnotationFqNames(modifierListOwner)) return true
if (allowMetaAnnotations) {
for (metaAnnotation in annotationType.annotations) {
- if (metaAnnotation.isAllOpenAnnotation(allowMetaAnnotations = false)) {
+ if (metaAnnotation.isAllOpenAnnotation(modifierListOwner, allowMetaAnnotations = false)) {
return true
}
}
diff --git a/plugins/allopen/src/AllOpenPlugin.kt b/plugins/allopen/allopen-cli/src/AllOpenPlugin.kt
similarity index 93%
rename from plugins/allopen/src/AllOpenPlugin.kt
rename to plugins/allopen/allopen-cli/src/AllOpenPlugin.kt
index 688ec5e1bf4..5eae22eb22a 100644
--- a/plugins/allopen/src/AllOpenPlugin.kt
+++ b/plugins/allopen/allopen-cli/src/AllOpenPlugin.kt
@@ -34,9 +34,11 @@ class AllOpenCommandLineProcessor : CommandLineProcessor {
companion object {
val ANNOTATION_OPTION = CliOption("annotation", "", "Annotation qualified names",
required = false, allowMultipleOccurrences = true)
+
+ val PLUGIN_ID = "org.jetbrains.kotlin.allopen"
}
- override val pluginId = "org.jetbrains.kotlin.allopen"
+ override val pluginId = PLUGIN_ID
override val pluginOptions = listOf(ANNOTATION_OPTION)
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) = when (option) {
@@ -54,6 +56,6 @@ class AllOpenComponentRegistrar : ComponentRegistrar {
val annotations = configuration.get(AllOpenConfigurationKeys.ANNOTATION) ?: return
if (annotations.isEmpty()) return
- DeclarationAttributeAltererExtension.registerExtension(project, AllOpenDeclarationAttributeAltererExtension(annotations))
+ DeclarationAttributeAltererExtension.registerExtension(project, CliAllOpenDeclarationAttributeAltererExtension(annotations))
}
}
\ No newline at end of file
diff --git a/plugins/allopen/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor b/plugins/allopen/allopen-cli/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
similarity index 100%
rename from plugins/allopen/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
rename to plugins/allopen/allopen-cli/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
diff --git a/plugins/allopen/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar b/plugins/allopen/allopen-cli/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
similarity index 100%
rename from plugins/allopen/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
rename to plugins/allopen/allopen-cli/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
diff --git a/plugins/allopen/testData/bytecodeListing/allOpenOnNotClasses.kt b/plugins/allopen/allopen-cli/testData/bytecodeListing/allOpenOnNotClasses.kt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/allOpenOnNotClasses.kt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/allOpenOnNotClasses.kt
diff --git a/plugins/allopen/testData/bytecodeListing/allOpenOnNotClasses.txt b/plugins/allopen/allopen-cli/testData/bytecodeListing/allOpenOnNotClasses.txt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/allOpenOnNotClasses.txt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/allOpenOnNotClasses.txt
diff --git a/plugins/allopen/testData/bytecodeListing/alreadyOpen.kt b/plugins/allopen/allopen-cli/testData/bytecodeListing/alreadyOpen.kt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/alreadyOpen.kt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/alreadyOpen.kt
diff --git a/plugins/allopen/testData/bytecodeListing/alreadyOpen.txt b/plugins/allopen/allopen-cli/testData/bytecodeListing/alreadyOpen.txt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/alreadyOpen.txt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/alreadyOpen.txt
diff --git a/plugins/allopen/allopen-cli/testData/bytecodeListing/explicitFinal.kt b/plugins/allopen/allopen-cli/testData/bytecodeListing/explicitFinal.kt
new file mode 100644
index 00000000000..efc2e0b18b2
--- /dev/null
+++ b/plugins/allopen/allopen-cli/testData/bytecodeListing/explicitFinal.kt
@@ -0,0 +1,18 @@
+annotation class AllOpen
+
+@AllOpen
+final class Test1
+
+@AllOpen
+class Test2 {
+ fun method1() {}
+ val prop1: String = ""
+
+ final fun method2() {}
+ final val prop2: String = ""
+ final var prop3: String = ""
+
+ // Modifier 'final' is not applicable to 'setter'
+ // var prop4: String = ""
+ // final set
+}
\ No newline at end of file
diff --git a/plugins/allopen/testData/bytecodeListing/explicitFinal.txt b/plugins/allopen/allopen-cli/testData/bytecodeListing/explicitFinal.txt
similarity index 62%
rename from plugins/allopen/testData/bytecodeListing/explicitFinal.txt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/explicitFinal.txt
index 4d80cc83279..6d540c89207 100644
--- a/plugins/allopen/testData/bytecodeListing/explicitFinal.txt
+++ b/plugins/allopen/allopen-cli/testData/bytecodeListing/explicitFinal.txt
@@ -13,9 +13,12 @@ public final class Test1 {
public class Test2 {
private final @org.jetbrains.annotations.NotNull field prop1: java.lang.String
private final @org.jetbrains.annotations.NotNull field prop2: java.lang.String
+ private @org.jetbrains.annotations.NotNull field prop3: java.lang.String
public method (): void
public @org.jetbrains.annotations.NotNull method getProp1(): java.lang.String
- public @org.jetbrains.annotations.NotNull method getProp2(): java.lang.String
+ public final @org.jetbrains.annotations.NotNull method getProp2(): java.lang.String
+ public final @org.jetbrains.annotations.NotNull method getProp3(): java.lang.String
public method method1(): void
public final method method2(): void
+ public final method setProp3(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
}
\ No newline at end of file
diff --git a/plugins/allopen/testData/bytecodeListing/metaAnnotation.kt b/plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.kt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/metaAnnotation.kt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.kt
diff --git a/plugins/allopen/testData/bytecodeListing/metaAnnotation.txt b/plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.txt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/metaAnnotation.txt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.txt
diff --git a/plugins/allopen/testData/bytecodeListing/nestedInner.kt b/plugins/allopen/allopen-cli/testData/bytecodeListing/nestedInner.kt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/nestedInner.kt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/nestedInner.kt
diff --git a/plugins/allopen/testData/bytecodeListing/nestedInner.txt b/plugins/allopen/allopen-cli/testData/bytecodeListing/nestedInner.txt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/nestedInner.txt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/nestedInner.txt
diff --git a/plugins/allopen/testData/bytecodeListing/noAllOpen.kt b/plugins/allopen/allopen-cli/testData/bytecodeListing/noAllOpen.kt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/noAllOpen.kt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/noAllOpen.kt
diff --git a/plugins/allopen/testData/bytecodeListing/noAllOpen.txt b/plugins/allopen/allopen-cli/testData/bytecodeListing/noAllOpen.txt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/noAllOpen.txt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/noAllOpen.txt
diff --git a/plugins/allopen/testData/bytecodeListing/sealed.kt b/plugins/allopen/allopen-cli/testData/bytecodeListing/sealed.kt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/sealed.kt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/sealed.kt
diff --git a/plugins/allopen/testData/bytecodeListing/sealed.txt b/plugins/allopen/allopen-cli/testData/bytecodeListing/sealed.txt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/sealed.txt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/sealed.txt
diff --git a/plugins/allopen/testData/bytecodeListing/severalAllOpen.kt b/plugins/allopen/allopen-cli/testData/bytecodeListing/severalAllOpen.kt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/severalAllOpen.kt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/severalAllOpen.kt
diff --git a/plugins/allopen/testData/bytecodeListing/severalAllOpen.txt b/plugins/allopen/allopen-cli/testData/bytecodeListing/severalAllOpen.txt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/severalAllOpen.txt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/severalAllOpen.txt
diff --git a/plugins/allopen/testData/bytecodeListing/simple.kt b/plugins/allopen/allopen-cli/testData/bytecodeListing/simple.kt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/simple.kt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/simple.kt
diff --git a/plugins/allopen/testData/bytecodeListing/simple.txt b/plugins/allopen/allopen-cli/testData/bytecodeListing/simple.txt
similarity index 100%
rename from plugins/allopen/testData/bytecodeListing/simple.txt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/simple.txt
diff --git a/plugins/allopen/testData/bytecodeListing/superClassAnnotation.kt b/plugins/allopen/allopen-cli/testData/bytecodeListing/superClassAnnotation.kt
similarity index 72%
rename from plugins/allopen/testData/bytecodeListing/superClassAnnotation.kt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/superClassAnnotation.kt
index 1a632a459ad..e68124c28e5 100644
--- a/plugins/allopen/testData/bytecodeListing/superClassAnnotation.kt
+++ b/plugins/allopen/allopen-cli/testData/bytecodeListing/superClassAnnotation.kt
@@ -20,9 +20,9 @@ interface Intf {
}
open class IntfImpl : Intf {
- fun intfImplMethod_ShouldBeFinal() {}
+ fun intfImplMethod_ShouldBeOpen() {}
}
-class IntfImpl2_ShouldBeFinalBecauseIntfIsAnInterface : IntfImpl() {
- fun intfImpl2Method_ShouldBeFinal() {}
+class IntfImpl2_ShouldBeOpen : IntfImpl() {
+ fun intfImpl2Method_ShouldBeOpen() {}
}
\ No newline at end of file
diff --git a/plugins/allopen/testData/bytecodeListing/superClassAnnotation.txt b/plugins/allopen/allopen-cli/testData/bytecodeListing/superClassAnnotation.txt
similarity index 85%
rename from plugins/allopen/testData/bytecodeListing/superClassAnnotation.txt
rename to plugins/allopen/allopen-cli/testData/bytecodeListing/superClassAnnotation.txt
index 86363218132..13260fd2635 100644
--- a/plugins/allopen/testData/bytecodeListing/superClassAnnotation.txt
+++ b/plugins/allopen/allopen-cli/testData/bytecodeListing/superClassAnnotation.txt
@@ -39,12 +39,12 @@ public interface Intf {
@kotlin.Metadata
public class IntfImpl {
public method (): void
- public final method intfImplMethod_ShouldBeFinal(): void
+ public method intfImplMethod_ShouldBeOpen(): void
public method intfMethod(): void
}
@kotlin.Metadata
-public final class IntfImpl2_ShouldBeFinalBecauseIntfIsAnInterface {
+public class IntfImpl2_ShouldBeOpen {
public method (): void
- public final method intfImpl2Method_ShouldBeFinal(): void
+ public method intfImpl2Method_ShouldBeOpen(): void
}
\ No newline at end of file
diff --git a/plugins/allopen/allopen-ide/allopen-ide.iml b/plugins/allopen/allopen-ide/allopen-ide.iml
new file mode 100644
index 00000000000..41c5789c7c0
--- /dev/null
+++ b/plugins/allopen/allopen-ide/allopen-ide.iml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/allopen/allopen-ide/src/AllOpenGradleProjectImportHandler.kt b/plugins/allopen/allopen-ide/src/AllOpenGradleProjectImportHandler.kt
new file mode 100644
index 00000000000..17f9ab344a2
--- /dev/null
+++ b/plugins/allopen/allopen-ide/src/AllOpenGradleProjectImportHandler.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010-2016 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.allopen.ide
+
+import org.jetbrains.kotlin.allopen.AllOpenCommandLineProcessor
+import org.jetbrains.kotlin.annotation.plugin.ide.AbstractGradleImportHandler
+import org.jetbrains.kotlin.utils.PathUtil
+
+class AllOpenGradleProjectImportHandler : AbstractGradleImportHandler() {
+ override val compilerPluginId = AllOpenCommandLineProcessor.PLUGIN_ID
+ override val pluginName = "allopen"
+ override val annotationOptionName = AllOpenCommandLineProcessor.ANNOTATION_OPTION.name
+ override val dataStorageTaskName = "allOpenDataStorageTask"
+ override val pluginJarFileFromIdea = PathUtil.getKotlinPathsForIdeaPlugin().allOpenPluginJarPath
+}
\ No newline at end of file
diff --git a/plugins/allopen/allopen-ide/src/AllOpenMavenProjectImportHandler.kt b/plugins/allopen/allopen-ide/src/AllOpenMavenProjectImportHandler.kt
new file mode 100644
index 00000000000..5e78491d4b0
--- /dev/null
+++ b/plugins/allopen/allopen-ide/src/AllOpenMavenProjectImportHandler.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2010-2016 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.allopen.ide
+
+import org.jetbrains.kotlin.allopen.AllOpenCommandLineProcessor
+import org.jetbrains.kotlin.annotation.plugin.ide.AbstractMavenImportHandler
+
+class AllOpenMavenProjectImportHandler : AbstractMavenImportHandler() {
+ private companion object {
+ val ANNOTATION_PARAMETER_PREFIX = "all-open:${AllOpenCommandLineProcessor.ANNOTATION_OPTION.name}="
+
+ private val SPRING_ALLOPEN_ANNOTATIONS = listOf(
+ "org.springframework.stereotype.Component",
+ "org.springframework.transaction.annotation.Transactional",
+ "org.springframework.scheduling.annotation.Async",
+ "org.springframework.cache.annotation.Cacheable"
+ )
+ }
+
+ override val compilerPluginId = AllOpenCommandLineProcessor.PLUGIN_ID
+ override val pluginName = "allopen"
+ override val annotationOptionName = AllOpenCommandLineProcessor.ANNOTATION_OPTION.name
+ override val mavenPluginArtifactName = "kotlin-maven-allopen"
+
+ override fun getAnnotations(enabledCompilerPlugins: List, compilerPluginOptions: List): List? {
+ if ("all-open" !in enabledCompilerPlugins && "spring" !in enabledCompilerPlugins) {
+ return null
+ }
+
+ val annotations = mutableListOf()
+ if ("spring" in enabledCompilerPlugins) {
+ annotations.addAll(SPRING_ALLOPEN_ANNOTATIONS)
+ }
+
+ annotations.addAll(compilerPluginOptions.mapNotNull { text ->
+ if (!text.startsWith(ANNOTATION_PARAMETER_PREFIX)) return@mapNotNull null
+ text.substring(ANNOTATION_PARAMETER_PREFIX.length)
+ })
+
+ return annotations
+ }
+}
\ No newline at end of file
diff --git a/plugins/allopen/allopen-ide/src/IdeAllOpenDeclarationAttributeAltererExtension.kt b/plugins/allopen/allopen-ide/src/IdeAllOpenDeclarationAttributeAltererExtension.kt
new file mode 100644
index 00000000000..8f564ae1503
--- /dev/null
+++ b/plugins/allopen/allopen-ide/src/IdeAllOpenDeclarationAttributeAltererExtension.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010-2016 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.allopen.ide
+
+import com.intellij.openapi.module.Module
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.roots.ProjectRootManager
+import com.intellij.openapi.roots.ProjectRootModificationTracker
+import com.intellij.psi.util.CachedValue
+import com.intellij.psi.util.CachedValueProvider
+import com.intellij.psi.util.CachedValuesManager
+import org.jetbrains.kotlin.allopen.AbstractAllOpenDeclarationAttributeAltererExtension
+import org.jetbrains.kotlin.idea.facet.KotlinFacet
+import org.jetbrains.kotlin.psi.KtModifierListOwner
+import org.jetbrains.kotlin.allopen.AllOpenCommandLineProcessor.Companion.PLUGIN_ID
+import org.jetbrains.kotlin.allopen.AllOpenCommandLineProcessor.Companion.ANNOTATION_OPTION
+import java.util.*
+
+class IdeAllOpenDeclarationAttributeAltererExtension(val project: Project) : AbstractAllOpenDeclarationAttributeAltererExtension() {
+ private companion object {
+ val ANNOTATION_OPTION_PREFIX = "plugin:$PLUGIN_ID:${ANNOTATION_OPTION.name}="
+ }
+
+ private val cache: CachedValue>> = cachedValue(project) {
+ CachedValueProvider.Result.create(WeakHashMap>(), ProjectRootModificationTracker.getInstance(project))
+ }
+
+ override fun getAllOpenAnnotationFqNames(modifierListOwner: KtModifierListOwner): List {
+ val project = modifierListOwner.project
+
+ val virtualFile = modifierListOwner.containingFile?.virtualFile ?: return emptyList()
+ val module = ProjectRootManager.getInstance(project).fileIndex.getModuleForFile(virtualFile) ?: return emptyList()
+
+ return cache.value.getOrPut(module) {
+ val kotlinFacet = KotlinFacet.get(module) ?: return@getOrPut emptyList()
+ val commonArgs = kotlinFacet.configuration.settings.compilerInfo.commonCompilerArguments ?: return@getOrPut emptyList()
+
+ commonArgs.pluginOptions?.filter { it.startsWith(ANNOTATION_OPTION_PREFIX) }
+ ?.map { it.substring(ANNOTATION_OPTION_PREFIX.length) }
+ ?: emptyList()
+ }
+ }
+
+ private fun cachedValue(project: Project, result: () -> CachedValueProvider.Result): CachedValue {
+ return CachedValuesManager.getManager(project).createCachedValue(result, false)
+ }
+}
\ No newline at end of file
diff --git a/plugins/allopen/testData/bytecodeListing/explicitFinal.kt b/plugins/allopen/testData/bytecodeListing/explicitFinal.kt
deleted file mode 100644
index 59f4e90b632..00000000000
--- a/plugins/allopen/testData/bytecodeListing/explicitFinal.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-annotation class AllOpen
-
-@AllOpen
-final class Test1
-
-@AllOpen
-class Test2 {
- fun method1() {}
- val prop1: String = ""
-
- final fun method2() {}
- val prop2: String = ""
-}
\ No newline at end of file
diff --git a/plugins/annotation-based-compiler-plugins-ide-support/annotation-based-compiler-plugins-ide-support.iml b/plugins/annotation-based-compiler-plugins-ide-support/annotation-based-compiler-plugins-ide-support.iml
new file mode 100644
index 00000000000..769bf18c2f0
--- /dev/null
+++ b/plugins/annotation-based-compiler-plugins-ide-support/annotation-based-compiler-plugins-ide-support.iml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/annotation-based-compiler-plugins-ide-support/src/AbstractGradleImportHandler.kt b/plugins/annotation-based-compiler-plugins-ide-support/src/AbstractGradleImportHandler.kt
new file mode 100644
index 00000000000..8d11d33e37d
--- /dev/null
+++ b/plugins/annotation-based-compiler-plugins-ide-support/src/AbstractGradleImportHandler.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010-2016 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.annotation.plugin.ide
+
+import com.intellij.openapi.externalSystem.model.DataNode
+import com.intellij.openapi.externalSystem.model.project.ModuleData
+import com.intellij.openapi.externalSystem.model.task.TaskData
+import org.jetbrains.kotlin.idea.configuration.GradleProjectImportHandler
+import org.jetbrains.kotlin.idea.facet.KotlinFacet
+import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
+import java.io.File
+
+abstract class AbstractGradleImportHandler : GradleProjectImportHandler {
+ private companion object {
+ private val TASK_DESCRIPTION_REGEX = "Supported annotations: (.*?); Compiler plugin classpath: (.*)".toRegex()
+ }
+
+ abstract val compilerPluginId: String
+ abstract val pluginName: String
+ abstract val annotationOptionName: String
+ abstract val dataStorageTaskName: String
+ abstract val pluginJarFileFromIdea: File
+
+ override fun invoke(facet: KotlinFacet, sourceSetNode: DataNode) {
+ modifyCompilerArgumentsForPlugin(facet, getPluginSetup(sourceSetNode),
+ compilerPluginId = compilerPluginId,
+ pluginName = pluginName,
+ annotationOptionName = annotationOptionName)
+ }
+
+ private fun getPluginSetup(
+ sourceSetNode: DataNode
+ ): AnnotationBasedCompilerPluginSetup? {
+ val moduleNode = sourceSetNode.parent ?: return null
+ if (moduleNode.data !is ModuleData) return null
+ val dataStorageTaskData = moduleNode.children.firstOrNull {
+ val data = it.data as? TaskData ?: return@firstOrNull false
+ data.name == dataStorageTaskName
+ }?.data as? TaskData ?: return null
+
+ val dataStorageTaskDescription = dataStorageTaskData.description ?: return null
+ val (annotationFqNamesList, classpathList) = TASK_DESCRIPTION_REGEX.matchEntire(
+ dataStorageTaskDescription)?.groupValues?.drop(1) ?: return null
+
+ val annotationFqNames = annotationFqNamesList.split(',')
+
+ // For now we can't use plugins from Gradle cause they're shaded. So we use ones from the IDEA plugin
+ val classpath = listOf(pluginJarFileFromIdea.absolutePath)
+
+ return AnnotationBasedCompilerPluginSetup(annotationFqNames, classpath)
+ }
+}
\ No newline at end of file
diff --git a/plugins/annotation-based-compiler-plugins-ide-support/src/AbstractMavenImportHandler.kt b/plugins/annotation-based-compiler-plugins-ide-support/src/AbstractMavenImportHandler.kt
new file mode 100644
index 00000000000..93be6d32aab
--- /dev/null
+++ b/plugins/annotation-based-compiler-plugins-ide-support/src/AbstractMavenImportHandler.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2010-2016 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.annotation.plugin.ide
+
+import org.jdom.Element
+import org.jdom.Text
+import org.jetbrains.idea.maven.project.MavenProject
+import org.jetbrains.kotlin.idea.facet.KotlinFacet
+import org.jetbrains.kotlin.idea.maven.MavenProjectImportHandler
+import org.jetbrains.kotlin.idea.maven.KotlinMavenImporter.Companion.KOTLIN_PLUGIN_GROUP_ID
+import org.jetbrains.kotlin.idea.maven.KotlinMavenImporter.Companion.KOTLIN_PLUGIN_ARTIFACT_ID
+import java.io.File
+
+abstract class AbstractMavenImportHandler : MavenProjectImportHandler {
+ abstract val compilerPluginId: String
+ abstract val pluginName: String
+ abstract val annotationOptionName: String
+ abstract val mavenPluginArtifactName: String
+
+ override fun invoke(facet: KotlinFacet, mavenProject: MavenProject) {
+ modifyCompilerArgumentsForPlugin(facet, getPluginSetup(mavenProject),
+ compilerPluginId = compilerPluginId,
+ pluginName = pluginName,
+ annotationOptionName = annotationOptionName)
+ }
+
+ abstract fun getAnnotations(enabledCompilerPlugins: List, compilerPluginOptions: List): List?
+
+ private fun getPluginSetup(mavenProject: MavenProject): AnnotationBasedCompilerPluginSetup? {
+ val kotlinPlugin = mavenProject.plugins.firstOrNull {
+ it.groupId == KOTLIN_PLUGIN_GROUP_ID && it.artifactId == KOTLIN_PLUGIN_ARTIFACT_ID
+ } ?: return null
+
+ val runtimeJarFile = mavenProject.dependencies
+ .firstOrNull { it.groupId == KOTLIN_PLUGIN_GROUP_ID &&
+ (it.artifactId == "kotlin-runtime" || it.artifactId == "kotlin-stdlib") }
+ ?.file ?: return null
+ val runtimeVersion = runtimeJarFile.parentFile.name
+
+ val mavenCompilerPluginJar = File(runtimeJarFile.parentFile.parentFile.parentFile,
+ "$mavenPluginArtifactName/$runtimeVersion/$mavenPluginArtifactName-$runtimeVersion.jar")
+
+ val configuration = kotlinPlugin.configurationElement ?: return null
+
+ val enabledCompilerPlugins = configuration.getElement("compilerPlugins")
+ ?.getElements()
+ ?.flatMap { plugin -> plugin.content.mapNotNull { (it as? Text)?.text } }
+ ?: emptyList()
+
+ val compilerPluginOptions = configuration.getElement("pluginOptions")
+ ?.getElements()
+ ?.flatMap { it.content }
+ ?.mapTo(mutableListOf()) { (it as Text).text }
+ ?: mutableListOf()
+
+ val annotationFqNames = getAnnotations(enabledCompilerPlugins, compilerPluginOptions) ?: return null
+ return AnnotationBasedCompilerPluginSetup(annotationFqNames, listOf(mavenCompilerPluginJar.absolutePath))
+ }
+
+ private fun Element.getElement(name: String) = content.firstOrNull { it is Element && it.name == name } as? Element
+
+ @Suppress("UNCHECKED_CAST")
+ private fun Element.getElements() = content.filterIsInstance()
+}
\ No newline at end of file
diff --git a/plugins/annotation-based-compiler-plugins-ide-support/src/idePluginUtils.kt b/plugins/annotation-based-compiler-plugins-ide-support/src/idePluginUtils.kt
new file mode 100644
index 00000000000..a2914fc1a16
--- /dev/null
+++ b/plugins/annotation-based-compiler-plugins-ide-support/src/idePluginUtils.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010-2016 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.annotation.plugin.ide
+
+import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
+import org.jetbrains.kotlin.idea.facet.KotlinFacet
+
+internal class AnnotationBasedCompilerPluginSetup(val annotationFqNames: List, val classpath: List)
+
+internal fun modifyCompilerArgumentsForPlugin(
+ facet: KotlinFacet,
+ setup: AnnotationBasedCompilerPluginSetup?,
+ compilerPluginId: String,
+ pluginName: String,
+ annotationOptionName: String
+) {
+ val compileInfo = facet.configuration.settings.compilerInfo
+
+ // investigate why copyBean() sometimes throws exceptions
+ val commonArguments = compileInfo.commonCompilerArguments ?: CommonCompilerArguments.DummyImpl()
+
+ /** See [CommonCompilerArguments.PLUGIN_OPTION_FORMAT] **/
+ val annotationOptions = setup?.annotationFqNames?.map { "plugin:$compilerPluginId:$annotationOptionName=$it" } ?: emptyList()
+
+ val oldPluginOptions = (commonArguments.pluginOptions ?: emptyArray()).filterTo(mutableListOf()) { !it.startsWith("plugin:$compilerPluginId:") }
+ val newPluginOptions = oldPluginOptions + annotationOptions
+
+ val oldPluginClasspaths = (commonArguments.pluginClasspaths ?: emptyArray()).filterTo(mutableListOf()) {
+ !it.substringAfterLast('/', missingDelimiterValue = "").matches("(kotlin-)?$pluginName-.*\\.jar".toRegex())
+ }
+
+ val newPluginClasspaths = oldPluginClasspaths + (setup?.classpath ?: emptyList())
+
+ commonArguments.pluginOptions = newPluginOptions.toTypedArray()
+ commonArguments.pluginClasspaths = newPluginClasspaths.toTypedArray()
+
+ compileInfo.commonCompilerArguments = commonArguments
+}
\ No newline at end of file
diff --git a/plugins/plugins-tests/plugins-tests.iml b/plugins/plugins-tests/plugins-tests.iml
index a7783d55b6e..a1a09d8797f 100755
--- a/plugins/plugins-tests/plugins-tests.iml
+++ b/plugins/plugins-tests/plugins-tests.iml
@@ -37,6 +37,6 @@
-
+
\ No newline at end of file
diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/allopen/AbstractBytecodeListingTestForAllOpen.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/allopen/AbstractBytecodeListingTestForAllOpen.kt
index 2cae74ffb82..bb338b66d21 100644
--- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/allopen/AbstractBytecodeListingTestForAllOpen.kt
+++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/allopen/AbstractBytecodeListingTestForAllOpen.kt
@@ -25,8 +25,8 @@ abstract class AbstractBytecodeListingTestForAllOpen : AbstractBytecodeListingTe
val ALLOPEN_ANNOTATIONS = listOf("AllOpen", "AllOpen2", "test.AllOpen")
}
- override fun setUpEnvironment(environment: KotlinCoreEnvironment) {
+ override fun setupEnvironment(environment: KotlinCoreEnvironment) {
DeclarationAttributeAltererExtension.registerExtension(
- environment.project, AllOpenDeclarationAttributeAltererExtension(ALLOPEN_ANNOTATIONS))
+ environment.project, CliAllOpenDeclarationAttributeAltererExtension(ALLOPEN_ANNOTATIONS))
}
}
\ No newline at end of file
diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/allopen/BytecodeListingTestForAllOpenGenerated.java b/plugins/plugins-tests/tests/org/jetbrains/kotlin/allopen/BytecodeListingTestForAllOpenGenerated.java
index ab84d923a19..46ecff1f568 100644
--- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/allopen/BytecodeListingTestForAllOpenGenerated.java
+++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/allopen/BytecodeListingTestForAllOpenGenerated.java
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.allopen;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
+import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
@@ -27,71 +28,71 @@ import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
-@TestMetadata("plugins/allopen/testData/bytecodeListing")
+@TestMetadata("plugins/allopen/allopen-cli/testData/bytecodeListing")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class BytecodeListingTestForAllOpenGenerated extends AbstractBytecodeListingTestForAllOpen {
public void testAllFilesPresentInBytecodeListing() throws Exception {
- KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("plugins/allopen/testData/bytecodeListing"), Pattern.compile("^(.+)\\.kt$"), true);
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("plugins/allopen/allopen-cli/testData/bytecodeListing"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("allOpenOnNotClasses.kt")
public void testAllOpenOnNotClasses() throws Exception {
- String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/testData/bytecodeListing/allOpenOnNotClasses.kt");
+ String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/allopen-cli/testData/bytecodeListing/allOpenOnNotClasses.kt");
doTest(fileName);
}
@TestMetadata("alreadyOpen.kt")
public void testAlreadyOpen() throws Exception {
- String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/testData/bytecodeListing/alreadyOpen.kt");
+ String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/allopen-cli/testData/bytecodeListing/alreadyOpen.kt");
doTest(fileName);
}
@TestMetadata("explicitFinal.kt")
public void testExplicitFinal() throws Exception {
- String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/testData/bytecodeListing/explicitFinal.kt");
+ String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/allopen-cli/testData/bytecodeListing/explicitFinal.kt");
doTest(fileName);
}
@TestMetadata("metaAnnotation.kt")
public void testMetaAnnotation() throws Exception {
- String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/testData/bytecodeListing/metaAnnotation.kt");
+ String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.kt");
doTest(fileName);
}
@TestMetadata("nestedInner.kt")
public void testNestedInner() throws Exception {
- String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/testData/bytecodeListing/nestedInner.kt");
+ String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/allopen-cli/testData/bytecodeListing/nestedInner.kt");
doTest(fileName);
}
@TestMetadata("noAllOpen.kt")
public void testNoAllOpen() throws Exception {
- String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/testData/bytecodeListing/noAllOpen.kt");
+ String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/allopen-cli/testData/bytecodeListing/noAllOpen.kt");
doTest(fileName);
}
@TestMetadata("sealed.kt")
public void testSealed() throws Exception {
- String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/testData/bytecodeListing/sealed.kt");
+ String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/allopen-cli/testData/bytecodeListing/sealed.kt");
doTest(fileName);
}
@TestMetadata("severalAllOpen.kt")
public void testSeveralAllOpen() throws Exception {
- String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/testData/bytecodeListing/severalAllOpen.kt");
+ String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/allopen-cli/testData/bytecodeListing/severalAllOpen.kt");
doTest(fileName);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
- String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/testData/bytecodeListing/simple.kt");
+ String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/allopen-cli/testData/bytecodeListing/simple.kt");
doTest(fileName);
}
@TestMetadata("superClassAnnotation.kt")
public void testSuperClassAnnotation() throws Exception {
- String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/testData/bytecodeListing/superClassAnnotation.kt");
+ String fileName = KotlinTestUtils.navigationMetadata("plugins/allopen/allopen-cli/testData/bytecodeListing/superClassAnnotation.kt");
doTest(fileName);
}
}