diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties
index c1646c43e85..5520aee3357 100644
--- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties
+++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties
@@ -441,6 +441,9 @@ replace.by.reconstructed.type=Replace by ''{0}''
suppress.warnings.family=Suppress Warnings
suppress.warning.for=Suppress ''{0}'' for {1} {2}
+reflection.not.found=Reflection not found in the classpath
+add.reflection.to.classpath=Add kotlin-reflect.jar to the classpath
+
# Kotlin Compiler Settings Tab
#Common
diff --git a/idea/resources/inspectionDescriptions/ReflectionNotFound.html b/idea/resources/inspectionDescriptions/ReflectionNotFound.html
new file mode 100644
index 00000000000..10b74f40c98
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/ReflectionNotFound.html
@@ -0,0 +1,5 @@
+
+
+This inspection reports expressions which use reflection features in the module which doesn't have a dependency on kotlin-reflect.jar.
+
+
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index a20598ccd35..2d34fbbb9d7 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -868,6 +868,13 @@
enabledByDefault="true"
level="WARNING"
/>
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ReflectionNotFoundInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ReflectionNotFoundInspection.kt
new file mode 100644
index 00000000000..31a6afece84
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ReflectionNotFoundInspection.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2010-2015 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.idea.inspections
+
+import com.intellij.codeInspection.LocalQuickFix
+import com.intellij.codeInspection.ProblemDescriptor
+import com.intellij.codeInspection.ProblemHighlightType
+import com.intellij.codeInspection.ProblemsHolder
+import com.intellij.openapi.extensions.Extensions
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.roots.OrderRootType
+import com.intellij.openapi.vfs.VfsUtil
+import com.intellij.openapi.vfs.VfsUtilCore
+import com.intellij.psi.PsiElementVisitor
+import org.jetbrains.kotlin.idea.JetBundle
+import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
+import org.jetbrains.kotlin.idea.configuration.ConfigureKotlinInProjectUtils
+import org.jetbrains.kotlin.idea.configuration.KotlinJavaModuleConfigurator
+import org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator
+import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider
+import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
+import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtil
+import org.jetbrains.kotlin.load.java.JvmAbi
+import org.jetbrains.kotlin.psi.JetDoubleColonExpression
+import org.jetbrains.kotlin.psi.JetFile
+import org.jetbrains.kotlin.psi.JetVisitorVoid
+import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
+import org.jetbrains.kotlin.utils.PathUtil
+import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
+import org.jetbrains.kotlin.utils.singletonOrEmptyList
+import java.io.File
+
+public class ReflectionNotFoundInspection : AbstractKotlinInspection() {
+ override fun runForWholeFile() = true
+
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
+ val file = holder.getFile()
+ val reportProblem =
+ file is JetFile &&
+ ProjectRootsUtil.isInProjectSource(file) &&
+ file.findModuleDescriptor().findClassAcrossModuleDependencies(JvmAbi.REFLECTION_FACTORY_IMPL) == null
+
+ return object : JetVisitorVoid() {
+ private fun createQuickFix(): LocalQuickFix? {
+ val pluginReflectJar = PathUtil.getKotlinPathsForIdeaPlugin().getReflectPath()
+ if (pluginReflectJar.exists()) {
+ val configurator =
+ Extensions.getExtensions(KotlinProjectConfigurator.EP_NAME).firstIsInstanceOrNull()
+
+ if (configurator != null) {
+ return AddReflectJarQuickFix(configurator, pluginReflectJar)
+ }
+ }
+
+ return null
+ }
+
+ override fun visitDoubleColonExpression(expression: JetDoubleColonExpression) {
+ if (reportProblem) {
+ holder.registerProblem(
+ expression.getDoubleColonTokenReference(),
+ JetBundle.message("reflection.not.found"),
+ ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
+ *(createQuickFix().singletonOrEmptyList().copyToArray())
+ )
+ }
+ }
+ }
+ }
+
+ class AddReflectJarQuickFix(
+ val configurator: KotlinJavaModuleConfigurator,
+ val pluginReflectJar: File
+ ) : LocalQuickFix {
+ override fun getName() = JetBundle.message("add.reflection.to.classpath")
+
+ override fun getFamilyName() = getName()
+
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor?) {
+ for (library in KotlinRuntimeLibraryUtil.findKotlinLibraries(project)) {
+ val runtimeJar = JavaRuntimePresentationProvider.getRuntimeJar(library) ?: continue
+ if (JavaRuntimePresentationProvider.getReflectJar(library) != null) continue
+
+ val model = library.getModifiableModel()
+
+ val libFilesDir = VfsUtilCore.virtualToIoFile(runtimeJar).getParent()
+ val reflectIoFile = File(libFilesDir, PathUtil.KOTLIN_JAVA_REFLECT_JAR)
+ if (reflectIoFile.exists()) {
+ model.addRoot(VfsUtil.getUrlForLibraryRoot(reflectIoFile), OrderRootType.CLASSES)
+ }
+ else {
+ val copied = configurator.copyFileToDir(pluginReflectJar, libFilesDir)!!
+ model.addRoot(VfsUtil.getUrlForLibraryRoot(copied), OrderRootType.CLASSES)
+ }
+
+ model.commit()
+
+ ConfigureKotlinInProjectUtils.showInfoNotification(
+ "${PathUtil.KOTLIN_JAVA_REFLECT_JAR} was added to the library ${library.getName()}"
+ )
+ }
+ }
+ }
+}