diff --git a/.idea/libraries/coverage_plugin.xml b/.idea/libraries/coverage_plugin.xml
new file mode 100644
index 00000000000..91df8c11739
--- /dev/null
+++ b/.idea/libraries/coverage_plugin.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/idea/idea.iml b/idea/idea.iml
index 21412d50803..ea77e4c848e 100644
--- a/idea/idea.iml
+++ b/idea/idea.iml
@@ -44,5 +44,6 @@
+
\ No newline at end of file
diff --git a/idea/src/META-INF/coverage.xml b/idea/src/META-INF/coverage.xml
new file mode 100644
index 00000000000..ce1756d8453
--- /dev/null
+++ b/idea/src/META-INF/coverage.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 2f695c90203..c34aef03115 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -15,6 +15,7 @@
com.intellij.copyright
JavaScriptDebugger
org.jetbrains.android
+ Coverage
diff --git a/idea/src/org/jetbrains/jet/plugin/coverage/KotlinCoverageExtension.kt b/idea/src/org/jetbrains/jet/plugin/coverage/KotlinCoverageExtension.kt
new file mode 100644
index 00000000000..3e29c7bf705
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/coverage/KotlinCoverageExtension.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2010-2014 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.jet.plugin.coverage
+
+import com.intellij.coverage.JavaCoverageEngineExtension
+import com.intellij.execution.configurations.RunConfigurationBase
+import org.jetbrains.jet.plugin.run.JetRunConfiguration
+import com.intellij.psi.PsiFile
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.coverage.CoverageSuitesBundle
+import java.io.File
+import org.jetbrains.jet.lang.psi.JetFile
+import org.jetbrains.jet.plugin.debugger.JetPositionManager
+import org.jetbrains.jet.plugin.caches.resolve.getModuleInfo
+import java.util.HashSet
+import org.jetbrains.jet.lang.psi.JetTreeVisitor
+import org.jetbrains.jet.lang.psi.JetDeclaration
+import com.intellij.openapi.roots.ProjectRootManager
+import org.jetbrains.jet.lang.psi.JetTreeVisitorVoid
+import org.jetbrains.annotations.TestOnly
+import com.intellij.openapi.application.ApplicationManager
+
+public class KotlinCoverageExtension(): JavaCoverageEngineExtension() {
+ override fun isApplicableTo(conf: RunConfigurationBase?): Boolean = conf is JetRunConfiguration
+
+ override fun collectOutputFiles(srcFile: PsiFile,
+ output: VirtualFile?,
+ testoutput: VirtualFile?,
+ suite: CoverageSuitesBundle,
+ classFiles: MutableSet): Boolean {
+ if (srcFile is JetFile) {
+ val fileIndex = ProjectRootManager.getInstance(srcFile.getProject()).getFileIndex()
+ if (fileIndex.isInLibraryClasses(srcFile.getVirtualFile()) ||
+ fileIndex.isInLibrarySource(srcFile.getVirtualFile())) {
+ return false
+ }
+
+ val classNames = ApplicationManager.getApplication().runReadAction> { collectOutputClassNames(srcFile) }
+
+ fun findUnder(name: String, root: VirtualFile?): File? {
+ if (root != null) {
+ val outputFile = File(root.getPath(), name + ".class")
+ if (outputFile.exists()) {
+ return outputFile
+ }
+ }
+ return null
+ }
+
+ classNames.map { findUnder(it, output) ?: findUnder(it, testoutput) }.filterNotNullTo(classFiles)
+ return true
+ }
+ return false
+ }
+
+ class object {
+ TestOnly public fun collectOutputClassNames(srcFile: JetFile): Set {
+ val typeMapper = JetPositionManager.createTypeMapper(srcFile, srcFile.getModuleInfo())
+ val classNames = HashSet()
+ srcFile.acceptChildren(object: JetTreeVisitorVoid() {
+ override fun visitDeclaration(dcl: JetDeclaration) {
+ val className = JetPositionManager.getClassNameForElement(dcl.getFirstChild(), typeMapper, srcFile, false)
+ if (className != null) {
+ classNames.add(className)
+ }
+ }
+ })
+ return classNames
+ }
+ }
+}
\ No newline at end of file