diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 25197088b5a..08b615972a8 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -271,8 +271,6 @@
-
-
diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java
new file mode 100644
index 00000000000..da08778e836
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2010-2013 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.libraries;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.lang.descriptors.*;
+import org.jetbrains.jet.lang.psi.JetDeclaration;
+import org.jetbrains.jet.lang.resolve.DescriptorUtils;
+import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
+import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder;
+import org.jetbrains.jet.lang.resolve.name.FqName;
+
+import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFQName;
+
+public final class DecompiledNavigationUtils {
+
+ private static final Logger LOG = Logger.getInstance(DecompiledNavigationUtils.class);
+
+ @Nullable
+ public static JetDeclaration findDeclarationForReference(
+ @NotNull Project project,
+ @NotNull DeclarationDescriptor referencedDescriptor
+ ) {
+ JetDeclaration declarationFromDecompiledClassFile = getDeclarationFromDecompiledClassFile(project, referencedDescriptor);
+ if (declarationFromDecompiledClassFile == null) {
+ return null;
+ }
+ return JetSourceNavigationHelper.replaceBySourceDeclarationIfPresent(declarationFromDecompiledClassFile);
+ }
+
+ @Nullable
+ private static JetDeclaration getDeclarationFromDecompiledClassFile(
+ @NotNull Project project,
+ @NotNull DeclarationDescriptor referencedDescriptor
+ ) {
+ DeclarationDescriptor effectiveReferencedDescriptor = getEffectiveReferencedDescriptor(referencedDescriptor);
+ VirtualFile virtualFile = findVirtualFileContainingDescriptor(project, effectiveReferencedDescriptor);
+
+ if (virtualFile == null || !DecompiledUtils.isKotlinCompiledFile(virtualFile)) return null;
+
+ JetDecompiledData data = JetDecompiledData.getDecompiledData(virtualFile, project);
+ JetDeclaration jetDeclaration = data.getDeclarationForDescriptor(effectiveReferencedDescriptor);
+ if (jetDeclaration != null) {
+ return jetDeclaration;
+ }
+ else {
+ LOG.warn("Could not find an element to navigate to for descriptor " + getFQName(effectiveReferencedDescriptor));
+ }
+ return null;
+ }
+
+ //TODO: should be done via some generic mechanism
+ @NotNull
+ private static DeclarationDescriptor getEffectiveReferencedDescriptor(@NotNull DeclarationDescriptor referencedDescriptor) {
+ if (referencedDescriptor instanceof VariableDescriptorForObject) {
+ ClassDescriptor objectClass = ((VariableDescriptorForObject) referencedDescriptor).getObjectClass();
+ if (objectClass.getKind() == ClassKind.OBJECT) {
+ return objectClass;
+ }
+ }
+ return referencedDescriptor;
+ }
+
+
+ /*
+ Find virtual file which contains the declaration of descriptor we're navigating to.
+ */
+ @Nullable
+ private static VirtualFile findVirtualFileContainingDescriptor(
+ @NotNull Project project,
+ @NotNull DeclarationDescriptor referencedDescriptor
+ ) {
+ FqName containerFqName = getContainerFqName(referencedDescriptor);
+ if (containerFqName == null) {
+ return null;
+ }
+ VirtualFileFinder fileFinder = ServiceManager.getService(project, VirtualFileFinder.class);
+ VirtualFile virtualFile = fileFinder.find(containerFqName);
+ if (virtualFile == null) {
+ return null;
+ }
+ return virtualFile;
+ }
+
+ //TODO: navigate to inner classes
+ @Nullable
+ private static FqName getContainerFqName(@NotNull DeclarationDescriptor referencedDescriptor) {
+ ClassOrNamespaceDescriptor
+ containerDescriptor = DescriptorUtils.getParentOfType(referencedDescriptor, ClassOrNamespaceDescriptor.class, false);
+ if (containerDescriptor instanceof NamespaceDescriptor) {
+ return PackageClassUtils.getPackageClassFqName(getFQName(containerDescriptor).toSafe());
+ }
+ if (containerDescriptor instanceof ClassDescriptor) {
+ ClassKind classKind = ((ClassDescriptor) containerDescriptor).getKind();
+ if (classKind == ClassKind.CLASS_OBJECT || classKind == ClassKind.ENUM_ENTRY) {
+ return getContainerFqName(containerDescriptor.getContainingDeclaration());
+ }
+ return getFQName(containerDescriptor).toSafe();
+ }
+ return null;
+ }
+
+ private DecompiledNavigationUtils() {
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetClsFileDecompiledPsiFileProvider.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsFileDecompiledPsiFileProvider.java
deleted file mode 100644
index f6fdf3b423f..00000000000
--- a/idea/src/org/jetbrains/jet/plugin/libraries/JetClsFileDecompiledPsiFileProvider.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2010-2013 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.libraries;
-
-import com.intellij.openapi.project.DumbService;
-import com.intellij.psi.ClsFileDecompiledPsiFileProvider;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiJavaFile;
-import com.intellij.psi.impl.compiled.ClsFileImpl;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class JetClsFileDecompiledPsiFileProvider implements ClsFileDecompiledPsiFileProvider {
- @Nullable
- @Override
- public PsiFile getDecompiledPsiFile(@NotNull PsiJavaFile psiFile) {
- ClsFileImpl clsFile = (ClsFileImpl)psiFile;
- if (JetDecompiledData.isKotlinFile(clsFile) && !DumbService.isDumb(psiFile.getProject())) {
- return JetDecompiledData.getDecompiledData(clsFile).getJetFile();
- }
- return null;
- }
-}
diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java
deleted file mode 100644
index 3b118790c4a..00000000000
--- a/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2010-2013 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.libraries;
-
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.impl.compiled.*;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jet.lang.psi.*;
-
-public class JetClsNavigationPolicy implements ClsCustomNavigationPolicy {
- @Override
- @Nullable
- public PsiElement getNavigationElement(@NotNull ClsClassImpl clsClass) {
- return getNavigationElementForMember(clsClass);
- }
-
- @Override
- @Nullable
- public PsiElement getNavigationElement(@NotNull ClsMethodImpl clsMethod) {
- return getNavigationElementForMember(clsMethod);
- }
-
- @Override
- @Nullable
- public PsiElement getNavigationElement(@NotNull ClsFieldImpl clsField) {
- return getNavigationElementForMember(clsField);
- }
-
- @Nullable
- private static PsiElement getNavigationElementForMember(@NotNull ClsMemberImpl clsMember) {
- VirtualFile virtualFile = clsMember.getContainingFile().getVirtualFile();
- if (virtualFile == null || !JetDecompiledData.isKotlinFile(clsMember.getProject(), virtualFile)) {
- return null;
- }
-
- JetDecompiledData decompiledData = JetDecompiledData.getDecompiledData((ClsFileImpl) clsMember.getContainingFile());
- JetDeclaration decompiledDeclaration = decompiledData.getJetDeclarationByClsElement(clsMember);
-
- if (decompiledDeclaration == null) {
- return null;
- }
-
- JetDeclaration sourceElement = decompiledDeclaration.accept(new SourceForDecompiledExtractingVisitor(), null);
- return sourceElement != null ? sourceElement : decompiledDeclaration;
- }
-
- private static class SourceForDecompiledExtractingVisitor extends JetVisitor {
- @Override
- public JetDeclaration visitNamedFunction(JetNamedFunction function, Void data) {
- return JetSourceNavigationHelper.getSourceFunction(function);
- }
-
- @Override
- public JetDeclaration visitProperty(JetProperty property, Void data) {
- return JetSourceNavigationHelper.getSourceProperty(property);
- }
-
- @Override
- public JetDeclaration visitObjectDeclaration(JetObjectDeclaration declaration, Void data) {
- return JetSourceNavigationHelper.getSourceClassOrObject(declaration);
- }
-
- @Override
- public JetDeclaration visitClass(JetClass klass, Void data) {
- return JetSourceNavigationHelper.getSourceClassOrObject(klass);
- }
- }
-}
diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java
index 0ebe5130a5d..4a85b43d1af 100644
--- a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java
+++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java
@@ -420,4 +420,32 @@ public class JetSourceNavigationHelper {
return original;
}
+
+ @NotNull
+ public static JetDeclaration replaceBySourceDeclarationIfPresent(@NotNull JetDeclaration original) {
+ JetDeclaration sourceElement = original.accept(new SourceForDecompiledExtractingVisitor(), null);
+ return sourceElement != null ? sourceElement : original;
+ }
+
+ private static class SourceForDecompiledExtractingVisitor extends JetVisitor {
+ @Override
+ public JetDeclaration visitNamedFunction(JetNamedFunction function, Void data) {
+ return getSourceFunction(function);
+ }
+
+ @Override
+ public JetDeclaration visitProperty(JetProperty property, Void data) {
+ return getSourceProperty(property);
+ }
+
+ @Override
+ public JetDeclaration visitObjectDeclaration(JetObjectDeclaration declaration, Void data) {
+ return getSourceClassOrObject(declaration);
+ }
+
+ @Override
+ public JetDeclaration visitClass(JetClass klass, Void data) {
+ return getSourceClassOrObject(klass);
+ }
+ }
}
diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java
index a999808a5ee..459e975f7a8 100644
--- a/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java
+++ b/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java
@@ -25,10 +25,12 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
+import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
+import org.jetbrains.jet.plugin.libraries.DecompiledNavigationUtils;
import org.jetbrains.jet.lang.resolve.java.JetClsMethod;
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
@@ -113,6 +115,14 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
if (psiElements.size() > 1) {
return null;
}
+ DeclarationDescriptor referencedDescriptor = context.get(BindingContext.REFERENCE_TARGET, myExpression);
+ if (referencedDescriptor != null) {
+ JetDeclaration declarationInDecompiledFile =
+ DecompiledNavigationUtils.findDeclarationForReference(myExpression.getProject(), referencedDescriptor);
+ if (declarationInDecompiledFile != null) {
+ return declarationInDecompiledFile;
+ }
+ }
Collection stdlibSymbols = resolveStandardLibrarySymbol(context);
if (stdlibSymbols.size() == 1) {
return stdlibSymbols.iterator().next();