diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 7404b2ae849..aa743022a9e 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -828,6 +828,8 @@
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/run/KotlinConsoleFilterProvider.kt b/idea/src/org/jetbrains/kotlin/idea/run/KotlinConsoleFilterProvider.kt
new file mode 100644
index 00000000000..9fd68ed4dc0
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/run/KotlinConsoleFilterProvider.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010-2017 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.run
+
+import com.intellij.execution.filters.ConsoleFilterProviderEx
+import com.intellij.execution.filters.Filter
+import com.intellij.execution.filters.HyperlinkInfo
+import com.intellij.openapi.editor.colors.CodeInsightColors
+import com.intellij.openapi.editor.colors.EditorColorsManager
+import com.intellij.openapi.fileEditor.OpenFileDescriptor
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.io.FileUtil
+import com.intellij.openapi.vfs.LocalFileSystem
+import com.intellij.psi.search.GlobalSearchScope
+
+class KotlinConsoleFilterProvider : ConsoleFilterProviderEx {
+ override fun getDefaultFilters(project: Project): Array {
+ return getDefaultFilters(project, GlobalSearchScope.allScope(project))
+ }
+
+ override fun getDefaultFilters(project: Project, scope: GlobalSearchScope): Array {
+ return arrayOf(KotlinConsoleFilter(project, scope))
+ }
+}
+
+class KotlinConsoleFilter(val project: Project, val scope: GlobalSearchScope) : Filter {
+ override fun applyFilter(line: String, entireLength: Int): Filter.Result? {
+ val messageSuffix = pattern.find(line) ?: return null
+ val pathStart = line.indexOf(":\\").takeIf { it >= 0 }?.minus(1)
+ ?: line.indexOf("/").takeIf { it >= 0 }
+ ?: return null
+ val path = line.substring(pathStart, messageSuffix.groups[1]!!.range.last + 1)
+ val lineNumber = Integer.parseInt(messageSuffix.groupValues[2]) - 1
+ val column = Integer.parseInt(messageSuffix.groupValues[3]) - 1
+ val attrs = EditorColorsManager.getInstance().globalScheme.getAttributes(CodeInsightColors.HYPERLINK_ATTRIBUTES)
+
+ val offset = entireLength - line.length
+ return Filter.Result(offset + pathStart, offset + messageSuffix.range.last, LocalFileHyperlinkInfo(path, lineNumber, column), attrs)
+ }
+
+ companion object {
+ private val pattern = Regex("""(\.kts?): \((\d+), (\d+)\):""")
+ }
+}
+
+class LocalFileHyperlinkInfo(val path: String, val line: Int, val column: Int) : HyperlinkInfo {
+ override fun navigate(project: Project) {
+ val f = LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(path))
+ if (f != null) {
+ OpenFileDescriptor(project, f, line, column).navigate(true)
+ }
+ }
+}
diff --git a/idea/tests/org/jetbrains/kotlin/idea/run/KotlinConsoleFilterTest.kt b/idea/tests/org/jetbrains/kotlin/idea/run/KotlinConsoleFilterTest.kt
new file mode 100644
index 00000000000..694947884a3
--- /dev/null
+++ b/idea/tests/org/jetbrains/kotlin/idea/run/KotlinConsoleFilterTest.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2010-2017 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.run
+
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
+import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
+
+class KotlinConsoleFilterTest : KotlinLightCodeInsightFixtureTestCase() {
+ fun testWindowsPath() {
+ val filter = KotlinConsoleFilter(project, GlobalSearchScope.allScope(project))
+ val line = """w: E:\Work\src\settings\jmx\JMX.kt: (54, 56): This cast can never succeed"""
+ val result = filter.applyFilter(line, line.length)!!
+ val resultItem = result.resultItems.single()
+ assertEquals(3, resultItem.getHighlightStartOffset())
+ assertEquals(44, resultItem.getHighlightEndOffset())
+ val hyperlinkInfo = resultItem.getHyperlinkInfo() as LocalFileHyperlinkInfo
+ assertEquals("E:\\Work\\src\\settings\\jmx\\JMX.kt", hyperlinkInfo.path)
+ }
+
+ fun testLinuxPath() {
+ val filter = KotlinConsoleFilter(project, GlobalSearchScope.allScope(project))
+ val line = """e: /Users/Work/app-web/src/main/kotlin/services/teamDirectory/NewOrEditTeamPageDescriptor.kt: (58, 52): The boolean literal does not conform to the expected type TeamMemberBuilder.() -> Unit"""
+ val result = filter.applyFilter(line, line.length)!!
+ val resultItem = result.resultItems.single()
+ assertEquals(3, resultItem.getHighlightStartOffset())
+ assertEquals(102, resultItem.getHighlightEndOffset())
+ }
+
+ override fun getProjectDescriptor() = KotlinLightProjectDescriptor.INSTANCE!!
+}
\ No newline at end of file