diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index ccdb4e7b10a..613085ada95 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -326,13 +326,11 @@
-
+
-
-
diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java
index 02e4803615a..643df3b5f68 100644
--- a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java
+++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java
@@ -55,7 +55,7 @@ public final class DecompiledNavigationUtils {
DeclarationDescriptor effectiveReferencedDescriptor = getEffectiveReferencedDescriptor(referencedDescriptor);
VirtualFile virtualFile = findVirtualFileContainingDescriptor(project, effectiveReferencedDescriptor);
- if (virtualFile == null || !DecompiledUtils.isKotlinCompiledFile(project, virtualFile)) return null;
+ if (virtualFile == null || !DecompiledUtils.isKotlinCompiledFile(virtualFile)) return null;
JetDecompiledData data = JetDecompiledData.getDecompiledData(virtualFile, project);
JetDeclaration jetDeclaration = data.getDeclarationForDescriptor(effectiveReferencedDescriptor);
diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java
index fb04feb02cd..b290a64c1f1 100644
--- a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java
+++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java
@@ -18,24 +18,57 @@ package org.jetbrains.jet.plugin.libraries;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass;
-import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinder;
+import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
+import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
+import org.jetbrains.jet.storage.LockBasedStorageManager;
public final class DecompiledUtils {
+ private static final String PACKAGE_FRAGMENT_SIGNATURE = PackageClassUtils.PACKAGE_CLASS_NAME_SUFFIX + "-";
- public static boolean isKotlinCompiledFile(@NotNull Project project, @NotNull VirtualFile file) {
+ public static boolean isKotlinCompiledFile(@NotNull VirtualFile file) {
if (!StdFileTypes.CLASS.getDefaultExtension().equals(file.getExtension())) {
return false;
}
- //TODO: check index
- KotlinJvmBinaryClass kotlinClass = VirtualFileFinder.SERVICE.getInstance(project).createKotlinClass(file);
- KotlinClassHeader header = kotlinClass.getClassHeader();
+
+ return isKotlinInternalClass(file) || checkFile(file);
+ }
+
+ public static boolean isKotlinInternalClass(@NotNull VirtualFile file) {
+ // FIXME: not sure if this is a good heuristic
+ String name = file.getName();
+ int pos = name.indexOf('$');
+ if (pos > 0) {
+ name = name.substring(0, pos) + ".class";
+ VirtualFile supposedHost = file.getParent().findChild(name);
+ if (supposedHost != null) {
+ return checkFile(supposedHost);
+ }
+ }
+
+ if (name.contains(PACKAGE_FRAGMENT_SIGNATURE)) {
+ KotlinClassHeader header = new VirtualFileKotlinClass(LockBasedStorageManager.NO_LOCKS, file).getClassHeader();
+ if (header != null && header.getKind() == KotlinClassHeader.Kind.PACKAGE_FRAGMENT) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static boolean checkFile(@NotNull VirtualFile file) {
+ KotlinClassHeader header = new VirtualFileKotlinClass(LockBasedStorageManager.NO_LOCKS, file).getClassHeader();
return header != null && header.getAnnotationData() != null;
}
+ public static CharSequence decompile(@NotNull VirtualFile file) {
+ Project project = ProjectManager.getInstance().getOpenProjects()[0]; // FIXME: get rid of project usage here
+ return JetDecompiledData.getDecompiledData(file, project).getFileText();
+ }
+
private DecompiledUtils() {
}
}
diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetClassFileDecompiler.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetClassFileDecompiler.java
new file mode 100644
index 00000000000..ae69f559de2
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetClassFileDecompiler.java
@@ -0,0 +1,45 @@
+/*
+ * 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.libraries;
+
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.compiled.ClassFileDecompilers;
+import com.intellij.psi.compiled.ClsStubBuilder;
+import org.jetbrains.annotations.NotNull;
+
+public class JetClassFileDecompiler extends ClassFileDecompilers.Full {
+ private final ClsStubBuilder stubBuilder = new JetClsStubBuilder();
+
+ @Override
+ public boolean accepts(@NotNull VirtualFile file) {
+ return DecompiledUtils.isKotlinCompiledFile(file);
+ }
+
+ @NotNull
+ @Override
+ public ClsStubBuilder getStubBuilder() {
+ return stubBuilder;
+ }
+
+ @NotNull
+ @Override
+ public FileViewProvider createFileViewProvider(@NotNull VirtualFile file, @NotNull PsiManager manager, boolean physical) {
+ return new JetClassFileViewProvider(manager, file, physical, DecompiledUtils.isKotlinInternalClass(file));
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetClassFileViewProvider.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetClassFileViewProvider.java
new file mode 100644
index 00000000000..508e93ce0ec
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetClassFileViewProvider.java
@@ -0,0 +1,64 @@
+/*
+ * 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.libraries;
+
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.compiled.ClsFileImpl;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.plugin.JetLanguage;
+
+public class JetClassFileViewProvider extends SingleRootFileViewProvider {
+ private final boolean isInternal;
+
+ public JetClassFileViewProvider(@NotNull PsiManager manager, @NotNull VirtualFile file, boolean physical, boolean internal) {
+ super(manager, file, physical, JetLanguage.INSTANCE);
+ isInternal = internal;
+ }
+
+ @NotNull
+ @Override
+ public CharSequence getContents() {
+ return isInternal ? "" : DecompiledUtils.decompile(getVirtualFile());
+ }
+
+ @Nullable
+ @Override
+ protected PsiFile createFile(@NotNull Project project, @NotNull VirtualFile file, @NotNull FileType fileType) {
+ return isInternal ? null : new JetDecompiledFile(this);
+ }
+
+ @NotNull
+ @Override
+ public SingleRootFileViewProvider createCopy(@NotNull VirtualFile copy) {
+ return new JetClassFileViewProvider(getManager(), copy, false, isInternal);
+ }
+
+ private static class JetDecompiledFile extends ClsFileImpl {
+ public JetDecompiledFile(FileViewProvider viewProvider) {
+ super(viewProvider);
+ }
+
+ @Override
+ public PsiFile getDecompiledPsiFile() {
+ return JetDecompiledData.getDecompiledData(getVirtualFile(), getProject()).getFile();
+ }
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetClsStubBuilder.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsStubBuilder.java
new file mode 100644
index 00000000000..848707ab28c
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsStubBuilder.java
@@ -0,0 +1,46 @@
+/*
+ * 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.libraries;
+
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.compiled.ClsStubBuilder;
+import com.intellij.psi.impl.compiled.ClassFileStubBuilder;
+import com.intellij.psi.impl.compiled.ClsFileImpl;
+import com.intellij.psi.stubs.PsiFileStub;
+import com.intellij.util.cls.ClsFormatException;
+import com.intellij.util.indexing.FileContent;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class JetClsStubBuilder extends ClsStubBuilder {
+ @Override
+ public int getStubVersion() {
+ return ClassFileStubBuilder.STUB_VERSION + 1;
+ }
+
+ @Nullable
+ @Override
+ public PsiFileStub> buildFileStub(@NotNull FileContent content) throws ClsFormatException {
+ VirtualFile file = content.getFile();
+
+ if (DecompiledUtils.isKotlinInternalClass(file)) {
+ return null;
+ }
+
+ return ClsFileImpl.buildFileStub(file, content.getContent());
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java
deleted file mode 100644
index 5cf073e388b..00000000000
--- a/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java
+++ /dev/null
@@ -1,115 +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.google.common.collect.Maps;
-import com.intellij.AppTopics;
-import com.intellij.lang.Language;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter;
-import com.intellij.openapi.fileTypes.ContentBasedClassFileProcessor;
-import com.intellij.openapi.fileTypes.SyntaxHighlighter;
-import com.intellij.openapi.project.DumbService;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.impl.PsiDocumentManagerBase;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jet.lang.psi.JetFile;
-import org.jetbrains.jet.plugin.highlighter.JetHighlighter;
-
-import java.util.concurrent.ConcurrentMap;
-
-public final class JetContentBasedFileSubstitutor implements ContentBasedClassFileProcessor {
- private static final JetContentBasedFileSubstitutor instance = new JetContentBasedFileSubstitutor();
-
- private static final ConcurrentMap deferredDocumentBinding = Maps.newConcurrentMap();
-
- public static JetContentBasedFileSubstitutor getInstance() {
- return instance;
- }
-
- private JetContentBasedFileSubstitutor() {
- ApplicationManager.getApplication().getMessageBus().connect().subscribe(AppTopics.FILE_DOCUMENT_SYNC, new FileDocumentManagerAdapter() {
- @Override
- public void fileContentLoaded(@NotNull VirtualFile loadedFile, @NotNull Document document) {
- processDeferredBindings(loadedFile, document);
- }
-
- @Override
- public void fileContentReloaded(VirtualFile loadedFile, @NotNull Document document) {
- processDeferredBindings(loadedFile, document);
- }
-
- private void processDeferredBindings(VirtualFile loadedFile, @NotNull Document document) {
- JetFile file = deferredDocumentBinding.remove(loadedFile);
- if (file != null) {
- PsiDocumentManagerBase.cachePsi(document, file);
- }
- }
- });
- }
-
- @Override
- public boolean isApplicable(@Nullable final Project project, @NotNull final VirtualFile file) {
- if (project == null) {
- return false;
- }
-
- if (DumbService.isDumb(project)) {
- DumbService.getInstance(project).runWhenSmart(new Runnable() {
- @Override
- public void run() {
- if (DecompiledUtils.isKotlinCompiledFile(project, file)) {
- FileDocumentManager docManager = FileDocumentManager.getInstance();
- docManager.getDocument(file); // force getting document because it can be collected
- docManager.reloadFiles(file);
- }
- }
- });
- return false;
- }
-
- return DecompiledUtils.isKotlinCompiledFile(project, file);
- }
-
- @NotNull
- @Override
- public String obtainFileText(Project project, VirtualFile file) {
- if (file != null && DecompiledUtils.isKotlinCompiledFile(project, file)) {
- JetDecompiledData data = JetDecompiledData.getDecompiledData(file, project);
- deferredDocumentBinding.put(file, data.getFile());
-
- return data.getFileText();
- }
- return "";
- }
-
- @Override
- public Language obtainLanguageForFile(VirtualFile file) {
- return null;
- }
-
- @NotNull
- @Override
- public SyntaxHighlighter createHighlighter(Project project, VirtualFile vFile) {
- return new JetHighlighter();
- }
-}
-
diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java b/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java
deleted file mode 100644
index 843e10d88ae..00000000000
--- a/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java
+++ /dev/null
@@ -1,58 +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.stubindex.builder;
-
-import com.intellij.openapi.fileTypes.StdFileTypes;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiJavaFile;
-import com.intellij.psi.impl.compiled.ClsStubBuilderFactory;
-import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl;
-import com.intellij.psi.stubs.PsiFileStub;
-import com.intellij.util.cls.ClsFormatException;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
-import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass;
-import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
-import org.jetbrains.jet.storage.LockBasedStorageManager;
-
-/**
- * This class is needed to build an empty PSI stub for compiled package fragment classes. This results in these classes not showing up
- * in completion, go-to-class, etc.
- */
-public class EmptyPackageFragmentClsStubBuilderFactory extends ClsStubBuilderFactory {
-
- @Nullable
- @Override
- public PsiFileStub buildFileStub(VirtualFile file, byte[] bytes) throws ClsFormatException {
- return new PsiJavaFileStubImpl(null, true);
- }
-
- @Override
- public boolean canBeProcessed(VirtualFile file, byte[] bytes) {
- if (file.getName().contains(PackageClassUtils.PACKAGE_CLASS_NAME_SUFFIX + "-") &&
- StdFileTypes.CLASS.getDefaultExtension().equals(file.getExtension())) {
- KotlinClassHeader header = new VirtualFileKotlinClass(LockBasedStorageManager.NO_LOCKS, file).getClassHeader();
- return header != null && header.getKind() == KotlinClassHeader.Kind.PACKAGE_PART;
- }
- return false;
- }
-
- @Override
- public boolean isInnerClass(VirtualFile file) {
- return false;
- }
-}