diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 2f695c90203..69d3cdcc2fc 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -261,6 +261,8 @@
displayName="Kotlin Compiler"
parentId="project.propCompiler"/>
+
+
diff --git a/idea/src/org/jetbrains/jet/plugin/actions/KotlinQualifiedNameProvider.kt b/idea/src/org/jetbrains/jet/plugin/actions/KotlinQualifiedNameProvider.kt
new file mode 100644
index 00000000000..bce3c987ba0
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/actions/KotlinQualifiedNameProvider.kt
@@ -0,0 +1,51 @@
+/*
+ * 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.actions
+
+import com.intellij.ide.actions.QualifiedNameProvider
+import com.intellij.psi.PsiElement
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.editor.Editor
+import org.jetbrains.jet.lang.psi.JetProperty
+import org.jetbrains.jet.lang.psi.JetNamedFunction
+import org.jetbrains.jet.lang.psi.JetDeclaration
+import org.jetbrains.jet.plugin.caches.resolve.resolveToDescriptor
+import org.jetbrains.jet.lang.resolve.DescriptorUtils
+import org.jetbrains.jet.lang.psi.JetClassOrObject
+
+public class KotlinQualifiedNameProvider: QualifiedNameProvider {
+ override fun adjustElementToCopy(element: PsiElement?) = null
+
+ override fun getQualifiedName(element: PsiElement?): String? {
+ when (element) {
+ is JetClassOrObject -> return element.getFqName()?.asString()
+ is JetNamedFunction, is JetProperty -> {
+ val descriptor = (element as JetDeclaration).resolveToDescriptor()
+ val fqNameUnsafe = DescriptorUtils.getFqName(descriptor)
+ if (fqNameUnsafe.isSafe()) {
+ return fqNameUnsafe.asString()
+ }
+ }
+ }
+ return null
+ }
+
+ override fun qualifiedNameToElement(fqn: String?, project: Project?) = null
+
+ override fun insertQualifiedName(fqn: String?, element: PsiElement?, editor: Editor?, project: Project?) {
+ }
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/jet/plugin/actions/QualifiedNamesTest.kt b/idea/tests/org/jetbrains/jet/plugin/actions/QualifiedNamesTest.kt
new file mode 100644
index 00000000000..ba6159974b9
--- /dev/null
+++ b/idea/tests/org/jetbrains/jet/plugin/actions/QualifiedNamesTest.kt
@@ -0,0 +1,91 @@
+/*
+ * 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.actions
+
+import com.intellij.testFramework.LightCodeInsightTestCase
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase
+import org.jetbrains.jet.lang.psi.JetVisitorVoid
+import com.intellij.psi.PsiElement
+import org.jetbrains.jet.lang.psi.JetClass
+import org.jetbrains.jet.lang.psi.JetObjectDeclaration
+import com.intellij.ide.actions.CopyReferenceAction
+import org.jetbrains.jet.lang.psi.JetNamedDeclaration
+import java.util.ArrayList
+import kotlin.test.assertEquals
+
+public class QualifiedNamesTest: LightCodeInsightTestCase() {
+ fun testClassRef() {
+ LightPlatformCodeInsightTestCase.configureFromFileText(
+ "class.kt",
+ """
+ package foo.bar
+
+ class Klass {
+ class Nested
+
+ class object {
+ }
+ }
+
+ object Object {
+ }
+
+ val anonymous = object {
+ }
+ """
+ )
+ assertEquals(listOf("foo.bar.Klass", "foo.bar.Klass.Nested", null, "foo.bar.Object", "foo.bar.anonymous", null),
+ getQualifiedNamesForDeclarations())
+ }
+
+ fun testFunRef() {
+ LightPlatformCodeInsightTestCase.configureFromFileText(
+ "fun.kt",
+ """
+ package foo.bar
+
+ class Klass {
+ fun memberFun() {
+ }
+
+ val memberVal = ":)"
+ }
+
+ fun topLevelFun()
+
+ val topLevelVal = ":)"
+ """
+ )
+ assertEquals(listOf("foo.bar.Klass", "foo.bar.Klass.memberFun", "foo.bar.Klass.memberVal", "foo.bar.topLevelFun", "foo.bar.topLevelVal"),
+ getQualifiedNamesForDeclarations())
+ }
+
+ private fun getQualifiedNamesForDeclarations(): List {
+ val result = ArrayList()
+ LightPlatformCodeInsightTestCase.myFile.accept(object : JetVisitorVoid() {
+ override fun visitElement(element: PsiElement) {
+ element.acceptChildren(this)
+ }
+
+ override fun visitNamedDeclaration(declaration: JetNamedDeclaration) {
+ result.add(CopyReferenceAction.elementToFqn(declaration))
+ super.visitNamedDeclaration(declaration)
+ }
+ })
+ return result
+ }
+}
\ No newline at end of file