From a98532c46e2dc8780ec66ce361829a2b421613e9 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sun, 19 Feb 2012 20:49:18 +0400 Subject: [PATCH 01/43] Implemented simple class content subsitutor. --- idea/src/META-INF/plugin.xml | 4 +- .../JetContentBasedFileSubstitutor.java | 110 ++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 743a36840fb..a7a0110cd57 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -1,7 +1,7 @@ Kotlin Kotlin language support - @snapshot@ + snapshot JetBrains JUnit @@ -153,6 +153,8 @@ + + diff --git a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java new file mode 100644 index 00000000000..3f8bfa633af --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java @@ -0,0 +1,110 @@ +/* + * Copyright 2000-2012 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; + +import com.intellij.ide.highlighter.JavaClassFileType; +import com.intellij.lang.Language; +import com.intellij.openapi.fileTypes.ContentBasedClassFileProcessor; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.fileTypes.SyntaxHighlighter; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.StreamUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiModifierList; +import com.intellij.psi.impl.compiled.ClassFileStubBuilder; +import com.intellij.psi.impl.compiled.ClsAnnotationImpl; +import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.Arrays; + +/** + * @author Evgeny Gerashchenko + * @since 2/15/12 + */ +public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProcessor { + + @Override + public boolean isApplicable(Project project, VirtualFile vFile) { + return isKotlinClass(project, vFile); + } + + @NotNull + @Override + public String obtainFileText(Project project, VirtualFile file) { + return file.getNameWithoutExtension(); + } + + @Override + public Language obtainLanguageForFile(VirtualFile file) { + if (!file.getNameWithoutExtension().contains("$")) { + return JetLanguage.INSTANCE; + } + return null; + } + + @NotNull + @Override + public SyntaxHighlighter createHighlighter(Project project, VirtualFile vFile) { + return JetHighlighter.PROVIDER.create(JetFileType.INSTANCE, project, vFile); + } + + private static boolean isKotlinClass(Project project, VirtualFile file) { + if (!FileTypeManager.getInstance().isFileOfType(file, JavaClassFileType.INSTANCE)) { + return false; + } + PsiJavaFileStub javaStub = getJavaStub(project, file); + if (javaStub == null) { + return false; + } + // TODO multiple? + if (javaStub.getClasses().length != 1) { + throw new AssertionError("Multiple classes in file: " + Arrays.toString(javaStub.getClasses())); + } + PsiClass psiClass = javaStub.getClasses()[0]; + // TODO add better check + if (psiClass.getName().equals("namespace")) { + return true; + } + PsiModifierList modifierList = psiClass.getModifierList(); + if (modifierList != null) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (annotation instanceof ClsAnnotationImpl) { + if (((ClsAnnotationImpl) annotation).getStub().getText().startsWith("@jet.runtime.typeinfo.JetClass")) { + return true; + } + } + } + } + return false; + } + + private static PsiJavaFileStub getJavaStub(Project project, VirtualFile file) { + try { + byte[] bytes = StreamUtil.loadFromStream(file.getInputStream()); + return (PsiJavaFileStub) new ClassFileStubBuilder().buildStubTree(file, bytes, project); + } catch (IOException e) { + return null; + } + } + + +} +- From 2950d87b95960cd47ba2df9a6f9674c85146f220 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sun, 19 Feb 2012 21:05:44 +0400 Subject: [PATCH 02/43] Using JavaDescriptorResolver to resolve Kotlin compiled classes. --- .../JetContentBasedFileSubstitutor.java | 61 ++++++++++++++++--- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java index 3f8bfa633af..64026d1d4c2 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java @@ -22,15 +22,25 @@ import com.intellij.openapi.fileTypes.ContentBasedClassFileProcessor; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiAnnotation; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiModifierList; +import com.intellij.psi.*; +import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.impl.compiled.ClassFileStubBuilder; import com.intellij.psi.impl.compiled.ClsAnnotationImpl; +import com.intellij.psi.impl.compiled.ClsFileImpl; +import com.intellij.psi.impl.java.stubs.ClsStubPsiFactory; import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; +import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl; +import com.intellij.psi.stubs.PsiClassHolderFileStub; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.JetSemanticServices; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; +import org.jetbrains.jet.resolve.DescriptorRenderer; import java.io.IOException; import java.util.Arrays; @@ -49,12 +59,31 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc @NotNull @Override public String obtainFileText(Project project, VirtualFile file) { - return file.getNameWithoutExtension(); + StringBuilder builder = new StringBuilder(); + + JavaSemanticServices jss = new JavaSemanticServices( + project, + JetSemanticServices.createSemanticServices(project), + new BindingTraceContext()); + PsiJavaFileStub js = getJavaStub(project, file); + if (js != null) { + if (js.getPackageName() != null && js.getPackageName().length() > 0) { + builder.append("package ").append(js.getPackageName()).append(";\n\n"); + } + + PsiClass psiClass = js.getClasses()[0]; + JavaDescriptorResolver jdr = jss.getDescriptorResolver(); + ClassDescriptor cd = jdr.resolveClass(psiClass); + builder.append(DescriptorRenderer.TEXT.render(cd)); + } + return builder.toString(); } @Override public Language obtainLanguageForFile(VirtualFile file) { - if (!file.getNameWithoutExtension().contains("$")) { + // TODO using random project is ugly + Project firstProject = ProjectManager.getInstance().getOpenProjects()[0]; + if (isKotlinClass(firstProject, file) && !file.getNameWithoutExtension().contains("$")) { return JetLanguage.INSTANCE; } return null; @@ -63,7 +92,7 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc @NotNull @Override public SyntaxHighlighter createHighlighter(Project project, VirtualFile vFile) { - return JetHighlighter.PROVIDER.create(JetFileType.INSTANCE, project, vFile); + return new JetHighlighter(); } private static boolean isKotlinClass(Project project, VirtualFile file) { @@ -99,7 +128,23 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc private static PsiJavaFileStub getJavaStub(Project project, VirtualFile file) { try { byte[] bytes = StreamUtil.loadFromStream(file.getInputStream()); - return (PsiJavaFileStub) new ClassFileStubBuilder().buildStubTree(file, bytes, project); + final PsiJavaFileStubImpl stub = (PsiJavaFileStubImpl) new ClassFileStubBuilder().buildStubTree(file, bytes, project); + if (stub == null) { + return null; + } + stub.setPsiFactory(new ClsStubPsiFactory()); // TODO is it needed? + PsiManagerImpl manager = (PsiManagerImpl) PsiManager.getInstance(project); + ClsFileImpl fakeFile = new ClsFileImpl(manager, new ClassFileViewProvider(manager, file)) { + @NotNull + @Override + public PsiClassHolderFileStub getStub() { + return stub; + } + }; + + fakeFile.setPhysical(false); + stub.setPsi(fakeFile); + return stub; } catch (IOException e) { return null; } @@ -107,4 +152,4 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc } -- + From 7627cb6ed15a2f89f8f07757211ba2addf0ae07f Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sun, 19 Feb 2012 21:06:06 +0400 Subject: [PATCH 03/43] Removed redundant "final" in DescriptorRenderer. --- .../src/org/jetbrains/jet/resolve/DescriptorRenderer.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 260a15d1941..88330554c67 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -277,16 +277,15 @@ public class DescriptorRenderer implements Renderer { private void renderModality(Modality modality, StringBuilder builder) { switch (modality) { case FINAL: - builder.append("final"); + // do not need: final by default break; case OPEN: - builder.append("open"); + builder.append("open "); break; case ABSTRACT: - builder.append("abstract"); + builder.append("abstract "); break; } - builder.append(" "); } @Override From 608787f63951539b94b3d1c836385e57e2ccea58 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Mon, 20 Feb 2012 16:31:09 +0400 Subject: [PATCH 04/43] Added explicit return-type annotation for FunctionalList.iterator() --- examples/example-vfs/example-vfs.iws | 684 +++++++++++++++++++++++++++ 1 file changed, 684 insertions(+) create mode 100644 examples/example-vfs/example-vfs.iws diff --git a/examples/example-vfs/example-vfs.iws b/examples/example-vfs/example-vfs.iws new file mode 100644 index 00000000000..15d24f95214 --- /dev/null +++ b/examples/example-vfs/example-vfs.iws @@ -0,0 +1,684 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + localhost + 5050 + + + + + + + + + + + 1327918157442 + 1327918157442 + + + 1329817388175 + 1329817388175 + + + 1329820289968 + 1329820289968 + + + 1330347238095 + 1330347238095 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No facets are configured + + + + + + + + + + + + + + + 1.6 + + + + + + + + example-vfs + + + + + + + + + + + + + + + + From 16f4ec70e9d82dd0ab862b520835e4d649c1c7c3 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 1 Mar 2012 19:18:15 +0400 Subject: [PATCH 05/43] Replaced HashMap with LinkedHashMap in JavaClassMembersScope, JavaDescriptorResolver and JavaDescriptorResolverHelper (so the order of members is deterministic). --- .../jet/lang/resolve/java/JavaClassMembersScope.java | 2 +- .../jet/lang/resolve/java/JavaDescriptorResolver.java | 4 ++-- .../lang/resolve/java/JavaDescriptorResolverHelper.java | 7 ++----- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java index 4cbd5f9e910..e440e177042 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java @@ -84,7 +84,7 @@ public class JavaClassMembersScope extends JavaClassOrPackageScope { @Override public Collection getAllDescriptors() { if (allDescriptors == null) { - allDescriptors = Sets.newHashSet(); + allDescriptors = Sets.newLinkedHashSet(); allDescriptors.addAll(semanticServices.getDescriptorResolver().resolveMethods(psiClass, descriptor)); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 3400964075b..73980852505 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -1026,7 +1026,7 @@ public class JavaDescriptorResolver { ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass)); - Set descriptors = Sets.newHashSet(); + Set descriptors = Sets.newLinkedHashSet(); Map membersForProperties = scopeData.namedMembersMap; for (Map.Entry entry : membersForProperties.entrySet()) { NamedMembers namedMembers = entry.getValue(); @@ -1286,7 +1286,7 @@ public class JavaDescriptorResolver { final Set functions = new HashSet(); - Set functionsFromCurrent = Sets.newHashSet(); + Set functionsFromCurrent = Sets.newLinkedHashSet(); for (PsiMethodWrapper method : namedMembers.methods) { FunctionDescriptorImpl function = resolveMethodToFunctionDescriptor(owner, psiClass, method); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java index 44bccd6542d..346346a8212 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java @@ -18,14 +18,11 @@ package org.jetbrains.jet.lang.resolve.java; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiField; -import com.intellij.psi.PsiMember; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiParameter; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; +import java.util.LinkedHashMap; import java.util.Map; /** @@ -40,7 +37,7 @@ class JavaDescriptorResolverHelper { private final boolean staticMembers; private final boolean kotlin; - private Map namedMembersMap = new HashMap(); + private Map namedMembersMap = new LinkedHashMap(); private Builder(PsiClassWrapper psiClass, boolean staticMembers, boolean kotlin) { this.psiClass = psiClass; From 688fad7f8f1ba94715db3d9248266125a7e94a89 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 1 Mar 2012 20:02:30 +0400 Subject: [PATCH 06/43] Added COMPACT descriptor renderer (without "defined in ...") --- .../jet/resolve/DescriptorRenderer.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 88330554c67..b4374517a68 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -37,6 +37,13 @@ import java.util.List; */ public class DescriptorRenderer implements Renderer { + public static final DescriptorRenderer COMPACT = new DescriptorRenderer() { + @Override + protected boolean shouldRenderDefinedIn() { + return false; + } + }; + public static final DescriptorRenderer TEXT = new DescriptorRenderer(); public static final DescriptorRenderer HTML = new DescriptorRenderer() { @@ -182,10 +189,16 @@ public class DescriptorRenderer implements Renderer { if (declarationDescriptor == null) return lt() + "null>"; StringBuilder stringBuilder = new StringBuilder(); declarationDescriptor.accept(rootVisitor, stringBuilder); - appendDefinedIn(declarationDescriptor, stringBuilder); + if (shouldRenderDefinedIn()) { + appendDefinedIn(declarationDescriptor, stringBuilder); + } return stringBuilder.toString(); } + protected boolean shouldRenderDefinedIn() { + return true; + } + private void appendDefinedIn(DeclarationDescriptor declarationDescriptor, StringBuilder stringBuilder) { stringBuilder.append(" ").append(renderMessage("defined in")).append(" "); @@ -198,7 +211,9 @@ public class DescriptorRenderer implements Renderer { public String renderAsObject(@NotNull ClassDescriptor classDescriptor) { StringBuilder stringBuilder = new StringBuilder(); rootVisitor.renderClassDescriptor(classDescriptor, stringBuilder, "object"); - appendDefinedIn(classDescriptor, stringBuilder); + if (shouldRenderDefinedIn()) { + appendDefinedIn(classDescriptor, stringBuilder); + } return stringBuilder.toString(); } @@ -341,8 +356,7 @@ public class DescriptorRenderer implements Renderer { builder.append(", "); } } - builder.append("> "); - return true; + builder.append(">"); } return false; } From 2d492e5171880a882d759942898aa28e02d6894e Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 1 Mar 2012 20:05:24 +0400 Subject: [PATCH 07/43] Added rendering class members. --- .../JetContentBasedFileSubstitutor.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java index 64026d1d4c2..9cdfeb1f288 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java @@ -37,9 +37,11 @@ import com.intellij.psi.stubs.PsiClassHolderFileStub; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.resolve.DescriptorRenderer; import java.io.IOException; @@ -68,24 +70,32 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc PsiJavaFileStub js = getJavaStub(project, file); if (js != null) { if (js.getPackageName() != null && js.getPackageName().length() > 0) { - builder.append("package ").append(js.getPackageName()).append(";\n\n"); + builder.append("package ").append(js.getPackageName()).append("\n\n"); } PsiClass psiClass = js.getClasses()[0]; JavaDescriptorResolver jdr = jss.getDescriptorResolver(); ClassDescriptor cd = jdr.resolveClass(psiClass); - builder.append(DescriptorRenderer.TEXT.render(cd)); + if (cd != null) { + builder.append(DescriptorRenderer.COMPACT.render(cd)); + + builder.append(" {\n"); + + JetScope memberScope = cd.getDefaultType().getMemberScope(); + for (DeclarationDescriptor member : memberScope.getAllDescriptors()) { + if (member.getContainingDeclaration() == cd) { + builder.append(" ").append(DescriptorRenderer.COMPACT.render(member)).append("\n"); + } + } + + builder.append("}"); + } } return builder.toString(); } @Override public Language obtainLanguageForFile(VirtualFile file) { - // TODO using random project is ugly - Project firstProject = ProjectManager.getInstance().getOpenProjects()[0]; - if (isKotlinClass(firstProject, file) && !file.getNameWithoutExtension().contains("$")) { - return JetLanguage.INSTANCE; - } return null; } From 5baf50cb925725dd1ae9d5ce69e3a61a75d83ca7 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 1 Mar 2012 20:30:43 +0400 Subject: [PATCH 08/43] Provided PSI file for decompiled Kotlin classes. --- .../jet/plugin/JetContentBasedFileSubstitutor.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java index 9cdfeb1f288..9e5d8b6ded4 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java @@ -35,6 +35,7 @@ import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl; import com.intellij.psi.stubs.PsiClassHolderFileStub; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; @@ -105,6 +106,14 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc return new JetHighlighter(); } + @Nullable + @Override + public PsiFile getDecompiledPsiFile(PsiFile psiFile) { + Project project = psiFile.getProject(); + String text = obtainFileText(project, psiFile.getVirtualFile()); + return PsiFileFactory.getInstance(project).createFileFromText("", JetLanguage.INSTANCE, text); + } + private static boolean isKotlinClass(Project project, VirtualFile file) { if (!FileTypeManager.getInstance().isFileOfType(file, JavaClassFileType.INSTANCE)) { return false; From 61639e577ee6c33f3f0f5f0cde9c747a44af47b2 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 1 Mar 2012 21:18:28 +0400 Subject: [PATCH 09/43] Added basic decompilation for namespace classes. --- .../plugin/JetContentBasedFileSubstitutor.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java index 9e5d8b6ded4..18f7fdf06d4 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java @@ -22,7 +22,6 @@ import com.intellij.openapi.fileTypes.ContentBasedClassFileProcessor; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -39,10 +38,10 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; -import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.resolve.DescriptorRenderer; import java.io.IOException; @@ -76,14 +75,23 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc PsiClass psiClass = js.getClasses()[0]; JavaDescriptorResolver jdr = jss.getDescriptorResolver(); + + if (psiClass.getName().equals("namespace")) { // TODO better check for namespace + NamespaceDescriptor nd = jdr.resolveNamespace(js.getPackageName()); + + if (nd != null) { + for (DeclarationDescriptor member : nd.getMemberScope().getAllDescriptors()) { + builder.append(DescriptorRenderer.COMPACT.render(member)).append("\n\n"); + } + } + } ClassDescriptor cd = jdr.resolveClass(psiClass); if (cd != null) { builder.append(DescriptorRenderer.COMPACT.render(cd)); builder.append(" {\n"); - JetScope memberScope = cd.getDefaultType().getMemberScope(); - for (DeclarationDescriptor member : memberScope.getAllDescriptors()) { + for (DeclarationDescriptor member : cd.getDefaultType().getMemberScope().getAllDescriptors()) { if (member.getContainingDeclaration() == cd) { builder.append(" ").append(DescriptorRenderer.COMPACT.render(member)).append("\n"); } From e810d73286389432d35615e94d235b2786bc706e Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 1 Mar 2012 21:25:02 +0400 Subject: [PATCH 10/43] Some minor fixes in presentation of decompiled namespaces. --- .../JetContentBasedFileSubstitutor.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java index 18f7fdf06d4..8fb590c3515 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java @@ -70,7 +70,7 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc PsiJavaFileStub js = getJavaStub(project, file); if (js != null) { if (js.getPackageName() != null && js.getPackageName().length() > 0) { - builder.append("package ").append(js.getPackageName()).append("\n\n"); + builder.append("package ").append(js.getPackageName()).append("\n\n\n"); } PsiClass psiClass = js.getClasses()[0]; @@ -81,23 +81,27 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc if (nd != null) { for (DeclarationDescriptor member : nd.getMemberScope().getAllDescriptors()) { + if (member instanceof ClassDescriptor && member.getName().equals("namespace")) { + continue; + } builder.append(DescriptorRenderer.COMPACT.render(member)).append("\n\n"); } } - } - ClassDescriptor cd = jdr.resolveClass(psiClass); - if (cd != null) { - builder.append(DescriptorRenderer.COMPACT.render(cd)); + } else { + ClassDescriptor cd = jdr.resolveClass(psiClass); + if (cd != null) { + builder.append(DescriptorRenderer.COMPACT.render(cd)); - builder.append(" {\n"); + builder.append(" {\n"); - for (DeclarationDescriptor member : cd.getDefaultType().getMemberScope().getAllDescriptors()) { - if (member.getContainingDeclaration() == cd) { - builder.append(" ").append(DescriptorRenderer.COMPACT.render(member)).append("\n"); + for (DeclarationDescriptor member : cd.getDefaultType().getMemberScope().getAllDescriptors()) { + if (member.getContainingDeclaration() == cd) { + builder.append(" ").append(DescriptorRenderer.COMPACT.render(member)).append("\n\n"); + } } - } - builder.append("}"); + builder.append("}"); + } } } return builder.toString(); From ecf622dca41c6a4b05a0145063815723d3e9280b Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 1 Mar 2012 21:50:11 +0400 Subject: [PATCH 11/43] Replaced hash sets with linked hash sets in JavaPackageScope. --- .../jetbrains/jet/lang/resolve/java/JavaPackageScope.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java index eb1ab6c83b8..5ac083a7b56 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java @@ -31,7 +31,7 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import java.util.Collection; -import java.util.HashSet; +import java.util.LinkedHashSet; /** * @author abreslav @@ -91,7 +91,7 @@ public class JavaPackageScope extends JavaClassOrPackageScope { @Override public Collection getAllDescriptors() { if (allDescriptors == null) { - allDescriptors = Sets.newHashSet(); + allDescriptors = Sets.newLinkedHashSet(); final PsiPackage javaPackage = semanticServices.getDescriptorResolver().findPackage(packageFQN); @@ -118,7 +118,7 @@ public class JavaPackageScope extends JavaClassOrPackageScope { // TODO: Temp hack for collection function descriptors from java if (JvmAbi.PACKAGE_CLASS.equals(psiClass.getName())) { - HashSet methodNames = new HashSet(); + LinkedHashSet methodNames = new LinkedHashSet(); for (PsiMethod psiMethod : psiClass.getMethods()) { methodNames.add(psiMethod.getName()); } From b257a497d1c3071a9637143e39c10653b66097b5 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Fri, 2 Mar 2012 11:43:00 +0400 Subject: [PATCH 12/43] Added /* compiled code */ comments. --- .../JetContentBasedFileSubstitutor.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java index 8fb590c3515..a5806adcf91 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java @@ -36,9 +36,7 @@ import com.intellij.psi.stubs.PsiClassHolderFileStub; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; -import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; @@ -69,8 +67,11 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc new BindingTraceContext()); PsiJavaFileStub js = getJavaStub(project, file); if (js != null) { + builder.append(PsiBundle.message("psi.decompiled.text.header")); + builder.append("\n\n"); + if (js.getPackageName() != null && js.getPackageName().length() > 0) { - builder.append("package ").append(js.getPackageName()).append("\n\n\n"); + builder.append("package ").append(js.getPackageName()).append("\n\n"); } PsiClass psiClass = js.getClasses()[0]; @@ -81,10 +82,10 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc if (nd != null) { for (DeclarationDescriptor member : nd.getMemberScope().getAllDescriptors()) { - if (member instanceof ClassDescriptor && member.getName().equals("namespace")) { + if (member instanceof ClassDescriptor && member.getName().equals("namespace") || member instanceof NamespaceDescriptor) { continue; } - builder.append(DescriptorRenderer.COMPACT.render(member)).append("\n\n"); + appendMemberDescriptor(builder, member); } } } else { @@ -96,7 +97,8 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc for (DeclarationDescriptor member : cd.getDefaultType().getMemberScope().getAllDescriptors()) { if (member.getContainingDeclaration() == cd) { - builder.append(" ").append(DescriptorRenderer.COMPACT.render(member)).append("\n\n"); + builder.append(" "); + appendMemberDescriptor(builder, member); } } @@ -107,6 +109,17 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc return builder.toString(); } + private static void appendMemberDescriptor(StringBuilder builder, DeclarationDescriptor member) { + String decompiledComment = "/* " + PsiBundle.message("psi.decompiled.method.body") + " */"; + builder.append(DescriptorRenderer.COMPACT.render(member)); + if (member instanceof FunctionDescriptor) { + builder.append(" { ").append(decompiledComment).append(" }"); + } else if (member instanceof PropertyDescriptor) { + builder.append(" ").append(decompiledComment); + } + builder.append("\n\n"); + } + @Override public Language obtainLanguageForFile(VirtualFile file) { return null; From d989fdfd3e4d6e781928c0cbd255d93d5f174a0c Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Fri, 2 Mar 2012 17:00:46 +0400 Subject: [PATCH 13/43] Minor in DescriptorRenderer: added space after type parameters --- .../jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java index a5806adcf91..407f42f2fa1 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java @@ -34,7 +34,6 @@ import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl; import com.intellij.psi.stubs.PsiClassHolderFileStub; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.BindingTraceContext; @@ -131,7 +130,7 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc return new JetHighlighter(); } - @Nullable + @NotNull @Override public PsiFile getDecompiledPsiFile(PsiFile psiFile) { Project project = psiFile.getProject(); From 54a781edb6a14dc64c88d363bd163df5a58be611 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Fri, 2 Mar 2012 17:07:42 +0400 Subject: [PATCH 14/43] Got rid of loading java stubs from class files: using ClsFile from PsiManager.findFile() instead. --- .../JetContentBasedFileSubstitutor.java | 110 ++++++------------ 1 file changed, 37 insertions(+), 73 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java index 407f42f2fa1..004e3feb334 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java @@ -22,17 +22,9 @@ import com.intellij.openapi.fileTypes.ContentBasedClassFileProcessor; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.PsiManagerImpl; -import com.intellij.psi.impl.compiled.ClassFileStubBuilder; import com.intellij.psi.impl.compiled.ClsAnnotationImpl; -import com.intellij.psi.impl.compiled.ClsFileImpl; -import com.intellij.psi.impl.java.stubs.ClsStubPsiFactory; -import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; -import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl; -import com.intellij.psi.stubs.PsiClassHolderFileStub; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.*; @@ -41,7 +33,6 @@ import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; import org.jetbrains.jet.resolve.DescriptorRenderer; -import java.io.IOException; import java.util.Arrays; /** @@ -52,7 +43,33 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc @Override public boolean isApplicable(Project project, VirtualFile vFile) { - return isKotlinClass(project, vFile); + if (!FileTypeManager.getInstance().isFileOfType(vFile, JavaClassFileType.INSTANCE)) { + return false; + } + PsiClassOwner clsFile = (PsiClassOwner) PsiManager.getInstance(project).findFile(vFile); + if (clsFile == null) { + return false; + } + // TODO multiple? + if (clsFile.getClasses().length != 1) { + throw new AssertionError("Multiple classes in file: " + Arrays.toString(clsFile.getClasses())); + } + PsiClass psiClass = clsFile.getClasses()[0]; + // TODO add better check + if (psiClass.getName().equals("namespace")) { + return true; + } + PsiModifierList modifierList = psiClass.getModifierList(); + if (modifierList != null) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (annotation instanceof ClsAnnotationImpl) { + if (((ClsAnnotationImpl) annotation).getStub().getText().startsWith("@jet.runtime.typeinfo.JetClass")) { + return true; + } + } + } + } + return false; } @NotNull @@ -64,20 +81,24 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc project, JetSemanticServices.createSemanticServices(project), new BindingTraceContext()); - PsiJavaFileStub js = getJavaStub(project, file); - if (js != null) { + PsiClassOwner clsFile = (PsiClassOwner) PsiManager.getInstance(project).findFile(file); + if (clsFile != null) { builder.append(PsiBundle.message("psi.decompiled.text.header")); builder.append("\n\n"); - if (js.getPackageName() != null && js.getPackageName().length() > 0) { - builder.append("package ").append(js.getPackageName()).append("\n\n"); + String packageName = clsFile.getPackageName(); + if (packageName == null) { + packageName = ""; + } + if (packageName.length() > 0) { + builder.append("package ").append(packageName).append("\n\n"); } - PsiClass psiClass = js.getClasses()[0]; + PsiClass psiClass = clsFile.getClasses()[0]; JavaDescriptorResolver jdr = jss.getDescriptorResolver(); if (psiClass.getName().equals("namespace")) { // TODO better check for namespace - NamespaceDescriptor nd = jdr.resolveNamespace(js.getPackageName()); + NamespaceDescriptor nd = jdr.resolveNamespace(packageName); if (nd != null) { for (DeclarationDescriptor member : nd.getMemberScope().getAllDescriptors()) { @@ -137,62 +158,5 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc String text = obtainFileText(project, psiFile.getVirtualFile()); return PsiFileFactory.getInstance(project).createFileFromText("", JetLanguage.INSTANCE, text); } - - private static boolean isKotlinClass(Project project, VirtualFile file) { - if (!FileTypeManager.getInstance().isFileOfType(file, JavaClassFileType.INSTANCE)) { - return false; - } - PsiJavaFileStub javaStub = getJavaStub(project, file); - if (javaStub == null) { - return false; - } - // TODO multiple? - if (javaStub.getClasses().length != 1) { - throw new AssertionError("Multiple classes in file: " + Arrays.toString(javaStub.getClasses())); - } - PsiClass psiClass = javaStub.getClasses()[0]; - // TODO add better check - if (psiClass.getName().equals("namespace")) { - return true; - } - PsiModifierList modifierList = psiClass.getModifierList(); - if (modifierList != null) { - for (PsiAnnotation annotation : modifierList.getAnnotations()) { - if (annotation instanceof ClsAnnotationImpl) { - if (((ClsAnnotationImpl) annotation).getStub().getText().startsWith("@jet.runtime.typeinfo.JetClass")) { - return true; - } - } - } - } - return false; - } - - private static PsiJavaFileStub getJavaStub(Project project, VirtualFile file) { - try { - byte[] bytes = StreamUtil.loadFromStream(file.getInputStream()); - final PsiJavaFileStubImpl stub = (PsiJavaFileStubImpl) new ClassFileStubBuilder().buildStubTree(file, bytes, project); - if (stub == null) { - return null; - } - stub.setPsiFactory(new ClsStubPsiFactory()); // TODO is it needed? - PsiManagerImpl manager = (PsiManagerImpl) PsiManager.getInstance(project); - ClsFileImpl fakeFile = new ClsFileImpl(manager, new ClassFileViewProvider(manager, file)) { - @NotNull - @Override - public PsiClassHolderFileStub getStub() { - return stub; - } - }; - - fakeFile.setPhysical(false); - stub.setPsi(fakeFile); - return stub; - } catch (IOException e) { - return null; - } - } - - } From 72fbdfa65e24da12960c37117dd087eb6ffb5a4b Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Fri, 2 Mar 2012 18:34:25 +0400 Subject: [PATCH 15/43] Extracted JetDecompiledData from JetContentBasedFileSubstitutor. It saves parsed Kotlin tree and text to user data of ClsFileImpl --- .../JetContentBasedFileSubstitutor.java | 112 +---------- .../jet/plugin/JetDecompiledData.java | 185 ++++++++++++++++++ 2 files changed, 193 insertions(+), 104 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java diff --git a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java index 004e3feb334..0145296c867 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java @@ -16,24 +16,14 @@ package org.jetbrains.jet.plugin; -import com.intellij.ide.highlighter.JavaClassFileType; import com.intellij.lang.Language; import com.intellij.openapi.fileTypes.ContentBasedClassFileProcessor; -import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; -import com.intellij.psi.impl.compiled.ClsAnnotationImpl; +import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.compiled.ClsFileImpl; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.JetSemanticServices; -import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.resolve.BindingTraceContext; -import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; -import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; -import org.jetbrains.jet.resolve.DescriptorRenderer; - -import java.util.Arrays; /** * @author Evgeny Gerashchenko @@ -42,102 +32,18 @@ import java.util.Arrays; public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProcessor { @Override - public boolean isApplicable(Project project, VirtualFile vFile) { - if (!FileTypeManager.getInstance().isFileOfType(vFile, JavaClassFileType.INSTANCE)) { - return false; - } - PsiClassOwner clsFile = (PsiClassOwner) PsiManager.getInstance(project).findFile(vFile); - if (clsFile == null) { - return false; - } - // TODO multiple? - if (clsFile.getClasses().length != 1) { - throw new AssertionError("Multiple classes in file: " + Arrays.toString(clsFile.getClasses())); - } - PsiClass psiClass = clsFile.getClasses()[0]; - // TODO add better check - if (psiClass.getName().equals("namespace")) { - return true; - } - PsiModifierList modifierList = psiClass.getModifierList(); - if (modifierList != null) { - for (PsiAnnotation annotation : modifierList.getAnnotations()) { - if (annotation instanceof ClsAnnotationImpl) { - if (((ClsAnnotationImpl) annotation).getStub().getText().startsWith("@jet.runtime.typeinfo.JetClass")) { - return true; - } - } - } - } - return false; + public boolean isApplicable(Project project, VirtualFile file) { + return JetDecompiledData.getClsFileIfKotlin(project, file) != null; } @NotNull @Override public String obtainFileText(Project project, VirtualFile file) { - StringBuilder builder = new StringBuilder(); - - JavaSemanticServices jss = new JavaSemanticServices( - project, - JetSemanticServices.createSemanticServices(project), - new BindingTraceContext()); - PsiClassOwner clsFile = (PsiClassOwner) PsiManager.getInstance(project).findFile(file); + ClsFileImpl clsFile = JetDecompiledData.getClsFileIfKotlin(project, file); if (clsFile != null) { - builder.append(PsiBundle.message("psi.decompiled.text.header")); - builder.append("\n\n"); - - String packageName = clsFile.getPackageName(); - if (packageName == null) { - packageName = ""; - } - if (packageName.length() > 0) { - builder.append("package ").append(packageName).append("\n\n"); - } - - PsiClass psiClass = clsFile.getClasses()[0]; - JavaDescriptorResolver jdr = jss.getDescriptorResolver(); - - if (psiClass.getName().equals("namespace")) { // TODO better check for namespace - NamespaceDescriptor nd = jdr.resolveNamespace(packageName); - - if (nd != null) { - for (DeclarationDescriptor member : nd.getMemberScope().getAllDescriptors()) { - if (member instanceof ClassDescriptor && member.getName().equals("namespace") || member instanceof NamespaceDescriptor) { - continue; - } - appendMemberDescriptor(builder, member); - } - } - } else { - ClassDescriptor cd = jdr.resolveClass(psiClass); - if (cd != null) { - builder.append(DescriptorRenderer.COMPACT.render(cd)); - - builder.append(" {\n"); - - for (DeclarationDescriptor member : cd.getDefaultType().getMemberScope().getAllDescriptors()) { - if (member.getContainingDeclaration() == cd) { - builder.append(" "); - appendMemberDescriptor(builder, member); - } - } - - builder.append("}"); - } - } + return JetDecompiledData.getDecompiledData(clsFile).getText(); } - return builder.toString(); - } - - private static void appendMemberDescriptor(StringBuilder builder, DeclarationDescriptor member) { - String decompiledComment = "/* " + PsiBundle.message("psi.decompiled.method.body") + " */"; - builder.append(DescriptorRenderer.COMPACT.render(member)); - if (member instanceof FunctionDescriptor) { - builder.append(" { ").append(decompiledComment).append(" }"); - } else if (member instanceof PropertyDescriptor) { - builder.append(" ").append(decompiledComment); - } - builder.append("\n\n"); + return ""; } @Override @@ -154,9 +60,7 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc @NotNull @Override public PsiFile getDecompiledPsiFile(PsiFile psiFile) { - Project project = psiFile.getProject(); - String text = obtainFileText(project, psiFile.getVirtualFile()); - return PsiFileFactory.getInstance(project).createFileFromText("", JetLanguage.INSTANCE, text); + return JetDecompiledData.getDecompiledData((ClsFileImpl) psiFile).getJetFile(); } } diff --git a/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java new file mode 100644 index 00000000000..910c09c32be --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java @@ -0,0 +1,185 @@ +/* + * Copyright 2000-2012 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; + +import com.intellij.ide.highlighter.JavaClassFileType; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.psi.impl.compiled.ClsAnnotationImpl; +import com.intellij.psi.impl.compiled.ClsFileImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.JetSemanticServices; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; +import org.jetbrains.jet.resolve.DescriptorRenderer; + +import java.util.Arrays; + +/** + * @author Evgeny Gerashchenko + * @since 3/2/12 + */ +public class JetDecompiledData { + private JetFile myJetFile; + private String myText; +// private Map myClsElementsToJetElements = new HashMap(); + + private static final Object LOCK = new String("decompiled data lock"); + private static final Key USER_DATA_KEY = new Key("USER_DATA_KEY"); + + private JetDecompiledData() { + } + + @NotNull + public JetFile getJetFile() { + return myJetFile; + } + + public String getText() { + return myText; + } + + @Nullable + public static ClsFileImpl getClsFileIfKotlin(@NotNull Project project, @NotNull VirtualFile vFile) { + if (!FileTypeManager.getInstance().isFileOfType(vFile, JavaClassFileType.INSTANCE)) { + return null; + } + PsiFile psiFile = PsiManager.getInstance(project).findFile(vFile); + if (!(psiFile instanceof ClsFileImpl)) { + return null; + } + ClsFileImpl clsFile = (ClsFileImpl) psiFile; + // TODO multiple? + if (clsFile.getClasses().length != 1) { + throw new AssertionError("Multiple classes in file: " + Arrays.toString(clsFile.getClasses())); + } + PsiClass psiClass = clsFile.getClasses()[0]; + // TODO add better check + if (psiClass.getName().equals("namespace")) { + return clsFile; + } + PsiModifierList modifierList = psiClass.getModifierList(); + if (modifierList != null) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (annotation instanceof ClsAnnotationImpl) { + if (((ClsAnnotationImpl) annotation).getStub().getText().startsWith("@jet.runtime.typeinfo.JetClass")) { + return clsFile; + } + } + } + } + return null; + } + + @NotNull + public static JetDecompiledData getDecompiledData(@NotNull ClsFileImpl clsFile) { + synchronized (LOCK) { + if (clsFile.getUserData(USER_DATA_KEY) == null) { + clsFile.putUserData(USER_DATA_KEY, decompileData(clsFile)); + } + JetDecompiledData decompiledData = clsFile.getUserData(USER_DATA_KEY); + assert decompiledData != null; + return decompiledData; + } + } + + @NotNull + private static JetDecompiledData decompileData(@NotNull ClsFileImpl clsFile) { + JetDecompiledData result = new JetDecompiledData(); + + Project project = clsFile.getProject(); + result.myText = getJetText(project, clsFile.getVirtualFile()); + result.myJetFile = (JetFile) PsiFileFactory.getInstance(project).createFileFromText(clsFile.getName(), JetLanguage.INSTANCE, result.myText); + + return result; + } + + + @NotNull + private static String getJetText(Project project, VirtualFile file) { + StringBuilder builder = new StringBuilder(); + + JavaSemanticServices jss = new JavaSemanticServices( + project, + JetSemanticServices.createSemanticServices(project), + new BindingTraceContext()); + PsiClassOwner clsFile = (PsiClassOwner) PsiManager.getInstance(project).findFile(file); + if (clsFile != null) { + builder.append(PsiBundle.message("psi.decompiled.text.header")); + builder.append("\n\n"); + + String packageName = clsFile.getPackageName(); + if (packageName == null) { + packageName = ""; + } + if (packageName.length() > 0) { + builder.append("package ").append(packageName).append("\n\n"); + } + + PsiClass psiClass = clsFile.getClasses()[0]; + JavaDescriptorResolver jdr = jss.getDescriptorResolver(); + + if (psiClass.getName().equals("namespace")) { // TODO better check for namespace + NamespaceDescriptor nd = jdr.resolveNamespace(packageName); + + if (nd != null) { + for (DeclarationDescriptor member : nd.getMemberScope().getAllDescriptors()) { + if (member instanceof ClassDescriptor && member.getName().equals("namespace") || member instanceof NamespaceDescriptor) { + continue; + } + appendMemberDescriptor(builder, member); + } + } + } else { + ClassDescriptor cd = jdr.resolveClass(psiClass); + if (cd != null) { + builder.append(DescriptorRenderer.COMPACT.render(cd)); + + builder.append(" {\n"); + + for (DeclarationDescriptor member : cd.getDefaultType().getMemberScope().getAllDescriptors()) { + if (member.getContainingDeclaration() == cd) { + builder.append(" "); + appendMemberDescriptor(builder, member); + } + } + + builder.append("}"); + } + } + } + return builder.toString(); + } + + private static void appendMemberDescriptor(StringBuilder builder, DeclarationDescriptor member) { + String decompiledComment = "/* " + PsiBundle.message("psi.decompiled.method.body") + " */"; + builder.append(DescriptorRenderer.COMPACT.render(member)); + if (member instanceof FunctionDescriptor) { + builder.append(" { ").append(decompiledComment).append(" }"); + } else if (member instanceof PropertyDescriptor) { + builder.append(" ").append(decompiledComment); + } + builder.append("\n\n"); + } +} From 01ed1c3f75eeb6f3cc8c0cdb1c5aca03adda5bf6 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Fri, 2 Mar 2012 19:25:25 +0400 Subject: [PATCH 16/43] Added saving mapping from ClsElements to JetElements in compiled classes. --- .../jet/plugin/JetDecompiledData.java | 116 +++++++++++------- 1 file changed, 74 insertions(+), 42 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java index 910c09c32be..3bbef0a8b79 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java @@ -20,30 +20,38 @@ import com.intellij.ide.highlighter.JavaClassFileType; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.compiled.ClsAnnotationImpl; +import com.intellij.psi.impl.compiled.ClsElementImpl; import com.intellij.psi.impl.compiled.ClsFileImpl; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; /** * @author Evgeny Gerashchenko * @since 3/2/12 */ +@SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") public class JetDecompiledData { private JetFile myJetFile; private String myText; -// private Map myClsElementsToJetElements = new HashMap(); + private Map myClsElementsToJetElements = new HashMap(); private static final Object LOCK = new String("decompiled data lock"); private static final Key USER_DATA_KEY = new Key("USER_DATA_KEY"); @@ -56,10 +64,15 @@ public class JetDecompiledData { return myJetFile; } + @NotNull public String getText() { return myText; } + public JetDeclaration getJetDeclarationByClsElement(ClsElementImpl clsElement) { + return myClsElementsToJetElements.get(clsElement); + } + @Nullable public static ClsFileImpl getClsFileIfKotlin(@NotNull Project project, @NotNull VirtualFile vFile) { if (!FileTypeManager.getInstance().isFileOfType(vFile, JavaClassFileType.INSTANCE)) { @@ -109,77 +122,96 @@ public class JetDecompiledData { JetDecompiledData result = new JetDecompiledData(); Project project = clsFile.getProject(); - result.myText = getJetText(project, clsFile.getVirtualFile()); - result.myJetFile = (JetFile) PsiFileFactory.getInstance(project).createFileFromText(clsFile.getName(), JetLanguage.INSTANCE, result.myText); + result.buildTextAndTree(project, clsFile.getVirtualFile()); return result; } - @NotNull - private static String getJetText(Project project, VirtualFile file) { + private void buildTextAndTree(Project project, VirtualFile file) { StringBuilder builder = new StringBuilder(); + BindingTraceContext trace = new BindingTraceContext(); JavaSemanticServices jss = new JavaSemanticServices( project, JetSemanticServices.createSemanticServices(project), - new BindingTraceContext()); - PsiClassOwner clsFile = (PsiClassOwner) PsiManager.getInstance(project).findFile(file); - if (clsFile != null) { - builder.append(PsiBundle.message("psi.decompiled.text.header")); - builder.append("\n\n"); + trace); + ClsFileImpl clsFile = (ClsFileImpl) PsiManager.getInstance(project).findFile(file); + assert clsFile != null; + builder.append(PsiBundle.message("psi.decompiled.text.header")); + builder.append("\n\n"); - String packageName = clsFile.getPackageName(); - if (packageName == null) { - packageName = ""; - } - if (packageName.length() > 0) { - builder.append("package ").append(packageName).append("\n\n"); + String packageName = clsFile.getPackageName(); + if (packageName.length() > 0) { + builder.append("package ").append(packageName).append("\n\n"); + } + + PsiClass psiClass = clsFile.getClasses()[0]; + JavaDescriptorResolver jdr = jss.getDescriptorResolver(); + + Map clsMembersToRanges = new HashMap(); + + if (psiClass.getName().equals("namespace")) { // TODO better check for namespace + NamespaceDescriptor nd = jdr.resolveNamespace(packageName); + + if (nd != null) { + for (DeclarationDescriptor member : nd.getMemberScope().getAllDescriptors()) { + if (member instanceof ClassDescriptor && member.getName().equals("namespace") || member instanceof NamespaceDescriptor) { + continue; + } + PsiElement clsElement = trace.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, member); + clsMembersToRanges.put(clsElement, appendMemberDescriptor(builder, member)); + } } + } else { + ClassDescriptor cd = jdr.resolveClass(psiClass); + if (cd != null) { + int classStart = builder.length(); - PsiClass psiClass = clsFile.getClasses()[0]; - JavaDescriptorResolver jdr = jss.getDescriptorResolver(); + builder.append(DescriptorRenderer.COMPACT.render(cd)); - if (psiClass.getName().equals("namespace")) { // TODO better check for namespace - NamespaceDescriptor nd = jdr.resolveNamespace(packageName); + builder.append(" {\n"); - if (nd != null) { - for (DeclarationDescriptor member : nd.getMemberScope().getAllDescriptors()) { - if (member instanceof ClassDescriptor && member.getName().equals("namespace") || member instanceof NamespaceDescriptor) { - continue; - } - appendMemberDescriptor(builder, member); + for (DeclarationDescriptor member : cd.getDefaultType().getMemberScope().getAllDescriptors()) { + if (member.getContainingDeclaration() == cd) { + builder.append(" "); + PsiElement clsElement = trace.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, member); + clsMembersToRanges.put(clsElement, appendMemberDescriptor(builder, member)); } } - } else { - ClassDescriptor cd = jdr.resolveClass(psiClass); - if (cd != null) { - builder.append(DescriptorRenderer.COMPACT.render(cd)); - builder.append(" {\n"); + builder.append("}"); - for (DeclarationDescriptor member : cd.getDefaultType().getMemberScope().getAllDescriptors()) { - if (member.getContainingDeclaration() == cd) { - builder.append(" "); - appendMemberDescriptor(builder, member); - } - } - - builder.append("}"); - } + PsiElement clsClass = trace.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, cd); + clsMembersToRanges.put(clsClass, new TextRange(classStart, builder.length())); } } - return builder.toString(); + + myText = builder.toString(); + myJetFile = (JetFile) PsiFileFactory.getInstance(project).createFileFromText("", JetLanguage.INSTANCE, myText); + for (Map.Entry clsMemberToRange : clsMembersToRanges.entrySet()) { + PsiElement clsMember = clsMemberToRange.getKey(); + assert clsMember instanceof ClsElementImpl; + + TextRange range = clsMemberToRange.getValue(); + JetDeclaration jetDeclaration = PsiTreeUtil.findElementOfClassAtRange(myJetFile, range.getStartOffset(), range.getEndOffset(), JetDeclaration.class); + assert jetDeclaration != null; + myClsElementsToJetElements.put((ClsElementImpl) clsMember, jetDeclaration); + } } - private static void appendMemberDescriptor(StringBuilder builder, DeclarationDescriptor member) { + private static TextRange appendMemberDescriptor(StringBuilder builder, DeclarationDescriptor member) { String decompiledComment = "/* " + PsiBundle.message("psi.decompiled.method.body") + " */"; + int startOffset = builder.length(); builder.append(DescriptorRenderer.COMPACT.render(member)); + int endOffset = builder.length(); if (member instanceof FunctionDescriptor) { builder.append(" { ").append(decompiledComment).append(" }"); + endOffset = builder.length(); } else if (member instanceof PropertyDescriptor) { builder.append(" ").append(decompiledComment); } builder.append("\n\n"); + return new TextRange(startOffset, endOffset); } } From 91adb13380348a4410587e71fe2c6b29b7120506 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Tue, 6 Mar 2012 23:27:47 +0400 Subject: [PATCH 17/43] Added JetDummyClassFileViewProvider which is needed to JetFiles created from libraries have link to physical VirtualFile instead of LightVirtualFile. --- .../jet/plugin/JetDecompiledData.java | 5 +- .../plugin/JetDummyClassFileViewProvider.java | 176 ++++++++++++++++++ 2 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/JetDummyClassFileViewProvider.java diff --git a/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java index 3bbef0a8b79..17a1c39a26d 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java @@ -136,7 +136,8 @@ public class JetDecompiledData { project, JetSemanticServices.createSemanticServices(project), trace); - ClsFileImpl clsFile = (ClsFileImpl) PsiManager.getInstance(project).findFile(file); + PsiManager psiManager = PsiManager.getInstance(project); + ClsFileImpl clsFile = (ClsFileImpl) psiManager.findFile(file); assert clsFile != null; builder.append(PsiBundle.message("psi.decompiled.text.header")); builder.append("\n\n"); @@ -188,7 +189,7 @@ public class JetDecompiledData { } myText = builder.toString(); - myJetFile = (JetFile) PsiFileFactory.getInstance(project).createFileFromText("", JetLanguage.INSTANCE, myText); + myJetFile = JetDummyClassFileViewProvider.createJetFile(psiManager, file, myText); for (Map.Entry clsMemberToRange : clsMembersToRanges.entrySet()) { PsiElement clsMember = clsMemberToRange.getKey(); assert clsMember instanceof ClsElementImpl; diff --git a/idea/src/org/jetbrains/jet/plugin/JetDummyClassFileViewProvider.java b/idea/src/org/jetbrains/jet/plugin/JetDummyClassFileViewProvider.java new file mode 100644 index 00000000000..ae26a36e3e3 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/JetDummyClassFileViewProvider.java @@ -0,0 +1,176 @@ +/* + * Copyright 2000-2012 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; + +import com.intellij.lang.Language; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.UserDataHolderBase; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.psi.impl.SharedPsiElementImplUtil; +import com.intellij.psi.impl.source.tree.LeafElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetFile; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * @author Evgeny Gerashchenko + * @since 3/2/12 + */ +public class JetDummyClassFileViewProvider extends UserDataHolderBase implements FileViewProvider { + private String myText; + private final PsiManager myManager; + private JetFile myJetFile = null; + private final VirtualFile myVirtualFile; + + public JetDummyClassFileViewProvider(@NotNull PsiManager manager, @NotNull VirtualFile file, String text) { + myManager = manager; + myVirtualFile = file; + myText = text; + + myJetFile = new JetFile(this); + } + + @Override + @NotNull + public PsiManager getManager() { + return myManager; + } + + @Override + @Nullable + public Document getDocument() { + return null; + } + + @Override + @NotNull + public CharSequence getContents() { + return myText; + } + + @Override + @NotNull + public VirtualFile getVirtualFile() { + return myVirtualFile; + } + + @Override + @NotNull + public Language getBaseLanguage() { + return JetLanguage.INSTANCE; + } + + @Override + @NotNull + public Set getLanguages() { + return Collections.singleton(getBaseLanguage()); + } + + @Override + public JetFile getPsi(@NotNull Language target) { + assert JetLanguage.INSTANCE == target; + return myJetFile; + } + + @Override + @NotNull + public List getAllFiles() { + return Collections.singletonList(myJetFile); + } + + @Override + public void beforeContentsSynchronized() { + } + + @Override + public void contentsSynchronized() { + } + + @Override + public boolean isEventSystemEnabled() { + return true; + } + + @Override + public boolean isPhysical() { + return false; + } + + @Override + public long getModificationStamp() { + return 0; + } + + @Override + public boolean supportsIncrementalReparse(@NotNull final Language rootLanguage) { + return true; + } + + @Override + public void rootChanged(@NotNull PsiFile psiFile) { + } + + @Override + public FileViewProvider clone(){ + throw new UnsupportedOperationException(); + } + + @Override + public PsiReference findReferenceAt(final int offset) { + return SharedPsiElementImplUtil.findReferenceAt(getPsi(getBaseLanguage()), offset); + } + + @Override + @Nullable + public PsiElement findElementAt(final int offset, @NotNull final Language language) { + return language == getBaseLanguage() ? findElementAt(offset) : null; + } + + + @Override + public PsiElement findElementAt(int offset, @NotNull Class lang) { + assert JetLanguage.class == lang; + return findElementAt(offset); + } + + @Override + public PsiElement findElementAt(final int offset) { + LeafElement element = myJetFile.calcTreeElement().findLeafElementAt(offset); + return element != null ? element.getPsi() : null; + } + + @Override + public PsiReference findReferenceAt(final int offsetInElement, @NotNull final Language language) { + assert JetLanguage.INSTANCE == language; + return findReferenceAt(offsetInElement); + } + + @NotNull + @Override + public FileViewProvider createCopy(@NotNull final VirtualFile copy) { + throw new UnsupportedOperationException(); + } + + public static JetFile createJetFile(PsiManager psiManager, VirtualFile file, String text) { + return new JetDummyClassFileViewProvider(psiManager, file, text).getPsi(JetLanguage.INSTANCE); + } +} From 2a9c1249573d5575a2d2010763ab986adf28f866 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Tue, 6 Mar 2012 23:28:07 +0400 Subject: [PATCH 18/43] Added implementation of ClsCustomNavigationPolicy for Kotlin libraries. --- idea/src/META-INF/plugin.xml | 1 + .../jet/plugin/JetClsNavigationPolicy.java | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 idea/src/org/jetbrains/jet/plugin/JetClsNavigationPolicy.java diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index a7a0110cd57..f209bfe7684 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -154,6 +154,7 @@ + diff --git a/idea/src/org/jetbrains/jet/plugin/JetClsNavigationPolicy.java b/idea/src/org/jetbrains/jet/plugin/JetClsNavigationPolicy.java new file mode 100644 index 00000000000..4499dce73cf --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/JetClsNavigationPolicy.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2012 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; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.impl.compiled.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetDeclaration; + +/** + * @author Evgeny Gerashchenko + * @since 3/2/12 + */ +public class JetClsNavigationPolicy implements ClsCustomNavigationPolicy { + @Override + public PsiElement getNavigationElement(@NotNull ClsClassImpl clsClass) { + return getJetDeclarationByClsElement(clsClass); + } + + @Override + public PsiElement getNavigationElement(@NotNull ClsMethodImpl clsMethod) { + return getJetDeclarationByClsElement(clsMethod); + } + + @Override + public PsiElement getNavigationElement(@NotNull ClsFieldImpl clsField) { + return getJetDeclarationByClsElement(clsField); + } + + private static JetDeclaration getJetDeclarationByClsElement(ClsElementImpl clsElement) { + JetDecompiledData decompiledData = JetDecompiledData.getDecompiledData((ClsFileImpl) clsElement.getContainingFile()); + return decompiledData.getJetDeclarationByClsElement(clsElement); + } +} From c2a300b6378e4e250ff9f86624038871657473d9 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Tue, 6 Mar 2012 23:42:06 +0400 Subject: [PATCH 19/43] Moved classes related to navigation to libraries to libraries subpackage of plugin package. --- idea/src/META-INF/plugin.xml | 4 ++-- .../jet/plugin/{ => libraries}/JetClsNavigationPolicy.java | 3 ++- .../{ => libraries}/JetContentBasedFileSubstitutor.java | 4 +++- .../jet/plugin/{ => libraries}/JetDecompiledData.java | 2 +- .../plugin/{ => libraries}/JetDummyClassFileViewProvider.java | 3 ++- 5 files changed, 10 insertions(+), 6 deletions(-) rename idea/src/org/jetbrains/jet/plugin/{ => libraries}/JetClsNavigationPolicy.java (94%) rename idea/src/org/jetbrains/jet/plugin/{ => libraries}/JetContentBasedFileSubstitutor.java (93%) rename idea/src/org/jetbrains/jet/plugin/{ => libraries}/JetDecompiledData.java (99%) rename idea/src/org/jetbrains/jet/plugin/{ => libraries}/JetDummyClassFileViewProvider.java (98%) diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index f209bfe7684..467bf1abcb9 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -153,8 +153,8 @@ - - + + diff --git a/idea/src/org/jetbrains/jet/plugin/JetClsNavigationPolicy.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java similarity index 94% rename from idea/src/org/jetbrains/jet/plugin/JetClsNavigationPolicy.java rename to idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java index 4499dce73cf..7b4b689afd0 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetClsNavigationPolicy.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package org.jetbrains.jet.plugin; +package org.jetbrains.jet.plugin.libraries; import com.intellij.psi.PsiElement; import com.intellij.psi.impl.compiled.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.plugin.libraries.JetDecompiledData; /** * @author Evgeny Gerashchenko diff --git a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java similarity index 93% rename from idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java rename to idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java index 0145296c867..acf14b819b8 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.jet.plugin; +package org.jetbrains.jet.plugin.libraries; import com.intellij.lang.Language; import com.intellij.openapi.fileTypes.ContentBasedClassFileProcessor; @@ -24,6 +24,8 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.compiled.ClsFileImpl; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.plugin.JetHighlighter; +import org.jetbrains.jet.plugin.libraries.JetDecompiledData; /** * @author Evgeny Gerashchenko diff --git a/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java similarity index 99% rename from idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java rename to idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java index 17a1c39a26d..034bd9a14f7 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.jet.plugin; +package org.jetbrains.jet.plugin.libraries; import com.intellij.ide.highlighter.JavaClassFileType; import com.intellij.openapi.fileTypes.FileTypeManager; diff --git a/idea/src/org/jetbrains/jet/plugin/JetDummyClassFileViewProvider.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java similarity index 98% rename from idea/src/org/jetbrains/jet/plugin/JetDummyClassFileViewProvider.java rename to idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java index ae26a36e3e3..caa76020665 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetDummyClassFileViewProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.jet.plugin; +package org.jetbrains.jet.plugin.libraries; import com.intellij.lang.Language; import com.intellij.openapi.editor.Document; @@ -26,6 +26,7 @@ import com.intellij.psi.impl.source.tree.LeafElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.plugin.JetLanguage; import java.util.Collections; import java.util.List; From 4b6e9557a6abeeaa9cd729882ca31575e9d901ad Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Tue, 6 Mar 2012 23:42:31 +0400 Subject: [PATCH 20/43] Made JetDummyClassFileViewProvider package-private. --- .../jet/plugin/libraries/JetDummyClassFileViewProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java index caa76020665..bd14bf0bfaf 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java @@ -36,7 +36,7 @@ import java.util.Set; * @author Evgeny Gerashchenko * @since 3/2/12 */ -public class JetDummyClassFileViewProvider extends UserDataHolderBase implements FileViewProvider { +class JetDummyClassFileViewProvider extends UserDataHolderBase implements FileViewProvider { private String myText; private final PsiManager myManager; private JetFile myJetFile = null; From 9658dd7c39a5a39bfbd377e81c92b2f963efa959 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Tue, 6 Mar 2012 23:47:15 +0400 Subject: [PATCH 21/43] Excluded classes from decompiled namespaces. --- .../org/jetbrains/jet/plugin/libraries/JetDecompiledData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java index 034bd9a14f7..d4fb9ad2b2b 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -157,7 +157,7 @@ public class JetDecompiledData { if (nd != null) { for (DeclarationDescriptor member : nd.getMemberScope().getAllDescriptors()) { - if (member instanceof ClassDescriptor && member.getName().equals("namespace") || member instanceof NamespaceDescriptor) { + if (member instanceof ClassDescriptor || member instanceof NamespaceDescriptor) { continue; } PsiElement clsElement = trace.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, member); From 8f5d469a0cf5e8c04ce58ed3af3c0d72a663afe6 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Wed, 7 Mar 2012 18:12:48 +0400 Subject: [PATCH 22/43] Replaced short names with fully qualified in DescriptorRenderer. --- .../src/org/jetbrains/jet/codegen/NamespaceCodegen.java | 5 +++-- .../org/jetbrains/jet/lang/resolve/DescriptorUtils.java | 4 +++- .../src/org/jetbrains/jet/resolve/DescriptorRenderer.java | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 6f1c1c255c1..a08afa84ef6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -21,6 +21,7 @@ import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; @@ -142,8 +143,8 @@ public class NamespaceCodegen { } String name = fqName.replace('.', '/'); - if(name.startsWith("")) { - name = name.substring("".length() + 1, name.length()); + if (name.startsWith(JavaDescriptorResolver.JAVA_ROOT)) { + name = name.substring(JavaDescriptorResolver.JAVA_ROOT.length() + 1, name.length()); } if (namespace) { name += "/" + JvmAbi.PACKAGE_CLASS; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index d4293240231..c426abea885 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -180,7 +180,9 @@ public class DescriptorUtils { public static String getFQName(DeclarationDescriptor descriptor) { DeclarationDescriptor container = descriptor.getContainingDeclaration(); - if (container != null && !(container instanceof ModuleDescriptor)) { + if (container != null && !(container instanceof ModuleDescriptor) + && !("".equals(container.getName()))) { + // TODO JavaNamespaceDescriptors should be refactored String baseName = getFQName(container); if (!baseName.isEmpty()) return baseName + "." + descriptor.getName(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index b4374517a68..4408ebf311d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -20,11 +20,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.Renderer; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; -import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.Variance; +import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lexer.JetTokens; import java.util.Collection; @@ -109,7 +110,9 @@ public class DescriptorRenderer implements Renderer { private String renderDefaultType(JetType type) { StringBuilder sb = new StringBuilder(); - sb.append(type.getConstructor()); + ClassifierDescriptor cd = type.getConstructor().getDeclarationDescriptor(); + sb.append(cd == null || cd instanceof TypeParameterDescriptor + ? type.getConstructor() : DescriptorUtils.getFQName(cd)); if (!type.getArguments().isEmpty()) { sb.append("<"); appendTypeProjections(sb, type.getArguments()); From b64e2ca886912975db20b7d8d2bcdd94f9315dfe Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Wed, 7 Mar 2012 18:15:00 +0400 Subject: [PATCH 23/43] Replaced asserts in JetDummyClassFileViewProvider with returning null. --- .../libraries/JetDummyClassFileViewProvider.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java index bd14bf0bfaf..baa8f2d0354 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java @@ -88,7 +88,9 @@ class JetDummyClassFileViewProvider extends UserDataHolderBase implements FileVi @Override public JetFile getPsi(@NotNull Language target) { - assert JetLanguage.INSTANCE == target; + if (JetLanguage.INSTANCE != target) { + return null; + } return myJetFile; } @@ -149,7 +151,9 @@ class JetDummyClassFileViewProvider extends UserDataHolderBase implements FileVi @Override public PsiElement findElementAt(int offset, @NotNull Class lang) { - assert JetLanguage.class == lang; + if (JetLanguage.class != lang) { + return null; + } return findElementAt(offset); } @@ -161,7 +165,9 @@ class JetDummyClassFileViewProvider extends UserDataHolderBase implements FileVi @Override public PsiReference findReferenceAt(final int offsetInElement, @NotNull final Language language) { - assert JetLanguage.INSTANCE == language; + if (JetLanguage.INSTANCE != language) { + return null; + } return findReferenceAt(offsetInElement); } From 351b2fd67614e5ac04cacf29da676ef56458894f Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sat, 10 Mar 2012 14:56:32 +0400 Subject: [PATCH 24/43] Specified return-type explicitly for FunctionalList.iterator() member function --- libraries/stdlib/src/concurrent/FunctionalList.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/stdlib/src/concurrent/FunctionalList.kt b/libraries/stdlib/src/concurrent/FunctionalList.kt index f441d73f47d..3d58b7dc1d1 100644 --- a/libraries/stdlib/src/concurrent/FunctionalList.kt +++ b/libraries/stdlib/src/concurrent/FunctionalList.kt @@ -23,7 +23,7 @@ abstract class FunctionalList(public val size: Int) { return new } - fun iterator() = object: Iterator { + fun iterator() : Iterator = object: Iterator { var cur = this@FunctionalList override fun next(): T { From 011d6fb5ee593a38024f7bcf344cde0251d0228a Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sat, 10 Mar 2012 15:32:10 +0400 Subject: [PATCH 25/43] Fixed navigation to non-Kotlin classes. --- .../jet/plugin/libraries/JetClsNavigationPolicy.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java index 7b4b689afd0..3a3ca4e3e3d 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java @@ -16,9 +16,11 @@ 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.JetDeclaration; import org.jetbrains.jet.plugin.libraries.JetDecompiledData; @@ -28,21 +30,29 @@ import org.jetbrains.jet.plugin.libraries.JetDecompiledData; */ public class JetClsNavigationPolicy implements ClsCustomNavigationPolicy { @Override + @Nullable public PsiElement getNavigationElement(@NotNull ClsClassImpl clsClass) { return getJetDeclarationByClsElement(clsClass); } @Override + @Nullable public PsiElement getNavigationElement(@NotNull ClsMethodImpl clsMethod) { return getJetDeclarationByClsElement(clsMethod); } @Override + @Nullable public PsiElement getNavigationElement(@NotNull ClsFieldImpl clsField) { return getJetDeclarationByClsElement(clsField); } + @Nullable private static JetDeclaration getJetDeclarationByClsElement(ClsElementImpl clsElement) { + VirtualFile virtualFile = clsElement.getContainingFile().getVirtualFile(); + if (virtualFile == null || JetDecompiledData.getClsFileIfKotlin(clsElement.getProject(), virtualFile) == null) { + return null; + } JetDecompiledData decompiledData = JetDecompiledData.getDecompiledData((ClsFileImpl) clsElement.getContainingFile()); return decompiledData.getJetDeclarationByClsElement(clsElement); } From 145e8ed936123592062462a5563669cf17bddb2e Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sat, 10 Mar 2012 16:25:27 +0400 Subject: [PATCH 26/43] Made checks for Kotlin namespace more robust. --- .../plugin/libraries/JetDecompiledData.java | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java index d4fb9ad2b2b..96736b1b505 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -27,6 +27,8 @@ import com.intellij.psi.impl.compiled.ClsAnnotationImpl; import com.intellij.psi.impl.compiled.ClsElementImpl; import com.intellij.psi.impl.compiled.ClsFileImpl; import com.intellij.psi.util.PsiTreeUtil; +import jet.runtime.typeinfo.JetClass; +import jet.runtime.typeinfo.JetMethod; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; @@ -37,6 +39,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.Arrays; @@ -49,6 +52,8 @@ import java.util.Map; */ @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") public class JetDecompiledData { + private static final String JET_CLASS = JetClass.class.getName(); + private static final String JET_METHOD = JetMethod.class.getName(); private JetFile myJetFile; private String myText; private Map myClsElementsToJetElements = new HashMap(); @@ -88,21 +93,7 @@ public class JetDecompiledData { throw new AssertionError("Multiple classes in file: " + Arrays.toString(clsFile.getClasses())); } PsiClass psiClass = clsFile.getClasses()[0]; - // TODO add better check - if (psiClass.getName().equals("namespace")) { - return clsFile; - } - PsiModifierList modifierList = psiClass.getModifierList(); - if (modifierList != null) { - for (PsiAnnotation annotation : modifierList.getAnnotations()) { - if (annotation instanceof ClsAnnotationImpl) { - if (((ClsAnnotationImpl) annotation).getStub().getText().startsWith("@jet.runtime.typeinfo.JetClass")) { - return clsFile; - } - } - } - } - return null; + return isKotlinNamespaceClass(psiClass) || isKotlinClass(psiClass) ? clsFile : null; } @NotNull @@ -152,7 +143,7 @@ public class JetDecompiledData { Map clsMembersToRanges = new HashMap(); - if (psiClass.getName().equals("namespace")) { // TODO better check for namespace + if (isKotlinNamespaceClass(psiClass)) { NamespaceDescriptor nd = jdr.resolveNamespace(packageName); if (nd != null) { @@ -215,4 +206,33 @@ public class JetDecompiledData { builder.append("\n\n"); return new TextRange(startOffset, endOffset); } + + private static boolean hasAnnotation(PsiModifierListOwner modifierListOwner, String qualifiedName) { + PsiModifierList modifierList = modifierListOwner.getModifierList(); + if (modifierList != null) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (annotation instanceof ClsAnnotationImpl) { + if (qualifiedName.equals(annotation.getQualifiedName())) { + return true; + } + } + } + } + return false; + } + + private static boolean isKotlinClass(PsiClass psiClass) { + return hasAnnotation(psiClass, JET_CLASS); + } + + private static boolean isKotlinNamespaceClass(PsiClass psiClass) { + if (JvmAbi.PACKAGE_CLASS.equals(psiClass.getName()) && !isKotlinClass(psiClass)) { + for (PsiMethod method : psiClass.getMethods()) { + if (hasAnnotation(method, JET_METHOD)) { + return true; + } + } + } + return false; + } } From 7b895de86fed4edcd896b4759ffc0f11acdcb21b Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sat, 10 Mar 2012 16:49:58 +0400 Subject: [PATCH 27/43] Replaced assertion with returning null when class file contains several classes. --- .../org/jetbrains/jet/plugin/libraries/JetDecompiledData.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java index 96736b1b505..c5191b6b21e 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -42,7 +42,6 @@ import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.resolve.DescriptorRenderer; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -88,9 +87,8 @@ public class JetDecompiledData { return null; } ClsFileImpl clsFile = (ClsFileImpl) psiFile; - // TODO multiple? if (clsFile.getClasses().length != 1) { - throw new AssertionError("Multiple classes in file: " + Arrays.toString(clsFile.getClasses())); + return null; } PsiClass psiClass = clsFile.getClasses()[0]; return isKotlinNamespaceClass(psiClass) || isKotlinClass(psiClass) ? clsFile : null; From d1f2c46d265f13abdf059fdce0bc99f69a0f29b6 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sat, 10 Mar 2012 19:23:32 +0400 Subject: [PATCH 28/43] Removed unnecessary "abstract" before "trait" in DescriptorRenderer. --- .../src/org/jetbrains/jet/resolve/DescriptorRenderer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 4408ebf311d..aef7c264b8c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -387,7 +387,9 @@ public class DescriptorRenderer implements Renderer { } public void renderClassDescriptor(ClassDescriptor descriptor, StringBuilder builder, String keyword) { - renderModality(descriptor.getModality(), builder); + if (descriptor.getKind() != ClassKind.TRAIT) { + renderModality(descriptor.getModality(), builder); + } builder.append(renderKeyword(keyword)).append(" "); renderName(descriptor, builder); renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder); From 6ac94758e24008c84d24d13b4e5b7127d27d518c Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sat, 10 Mar 2012 19:24:36 +0400 Subject: [PATCH 29/43] Added support for nested classes in decompiler. --- .../plugin/libraries/JetDecompiledData.java | 62 ++++++++++--------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java index c5191b6b21e..bfd4e79ffa9 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -59,8 +59,10 @@ public class JetDecompiledData { private static final Object LOCK = new String("decompiled data lock"); private static final Key USER_DATA_KEY = new Key("USER_DATA_KEY"); + private final Map myClsMembersToRanges; private JetDecompiledData() { + myClsMembersToRanges = new HashMap(); } @NotNull @@ -139,8 +141,6 @@ public class JetDecompiledData { PsiClass psiClass = clsFile.getClasses()[0]; JavaDescriptorResolver jdr = jss.getDescriptorResolver(); - Map clsMembersToRanges = new HashMap(); - if (isKotlinNamespaceClass(psiClass)) { NamespaceDescriptor nd = jdr.resolveNamespace(packageName); @@ -149,37 +149,20 @@ public class JetDecompiledData { if (member instanceof ClassDescriptor || member instanceof NamespaceDescriptor) { continue; } - PsiElement clsElement = trace.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, member); - clsMembersToRanges.put(clsElement, appendMemberDescriptor(builder, member)); + appendDescriptor(builder, member, trace.getBindingContext(), ""); + builder.append("\n"); } } } else { ClassDescriptor cd = jdr.resolveClass(psiClass); if (cd != null) { - int classStart = builder.length(); - - builder.append(DescriptorRenderer.COMPACT.render(cd)); - - builder.append(" {\n"); - - for (DeclarationDescriptor member : cd.getDefaultType().getMemberScope().getAllDescriptors()) { - if (member.getContainingDeclaration() == cd) { - builder.append(" "); - PsiElement clsElement = trace.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, member); - clsMembersToRanges.put(clsElement, appendMemberDescriptor(builder, member)); - } - } - - builder.append("}"); - - PsiElement clsClass = trace.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, cd); - clsMembersToRanges.put(clsClass, new TextRange(classStart, builder.length())); + appendDescriptor(builder, cd, trace.getBindingContext(), ""); } } myText = builder.toString(); myJetFile = JetDummyClassFileViewProvider.createJetFile(psiManager, file, myText); - for (Map.Entry clsMemberToRange : clsMembersToRanges.entrySet()) { + for (Map.Entry clsMemberToRange : myClsMembersToRanges.entrySet()) { PsiElement clsMember = clsMemberToRange.getKey(); assert clsMember instanceof ClsElementImpl; @@ -190,19 +173,40 @@ public class JetDecompiledData { } } - private static TextRange appendMemberDescriptor(StringBuilder builder, DeclarationDescriptor member) { + private void appendDescriptor(StringBuilder builder, DeclarationDescriptor descriptor, BindingContext bindingContext, String indent) { String decompiledComment = "/* " + PsiBundle.message("psi.decompiled.method.body") + " */"; + + builder.append(indent); + int startOffset = builder.length(); - builder.append(DescriptorRenderer.COMPACT.render(member)); + builder.append(DescriptorRenderer.COMPACT.render(descriptor)); int endOffset = builder.length(); - if (member instanceof FunctionDescriptor) { + + if (descriptor instanceof FunctionDescriptor) { builder.append(" { ").append(decompiledComment).append(" }"); endOffset = builder.length(); - } else if (member instanceof PropertyDescriptor) { + } else if (descriptor instanceof PropertyDescriptor) { builder.append(" ").append(decompiledComment); + } else if (descriptor instanceof ClassDescriptor) { + builder.append(" {\n"); + boolean firstPassed = false; + for (DeclarationDescriptor member : ((ClassDescriptor) descriptor).getDefaultType().getMemberScope().getAllDescriptors()) { + if (member.getContainingDeclaration() == descriptor) { + if (firstPassed) { + builder.append("\n"); + } else { + firstPassed = true; + } + appendDescriptor(builder, member, bindingContext, indent + " "); + } + } + builder.append(indent).append("}"); + endOffset = builder.length(); } - builder.append("\n\n"); - return new TextRange(startOffset, endOffset); + + builder.append("\n"); + PsiElement clsMember = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); + myClsMembersToRanges.put(clsMember, new TextRange(startOffset, endOffset)); } private static boolean hasAnnotation(PsiModifierListOwner modifierListOwner, String qualifiedName) { From e9bac5ce16e3726b767bbdcc9c3ec6af06fd6af5 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sat, 10 Mar 2012 20:29:00 +0400 Subject: [PATCH 30/43] Added better rendering for objects in DescriptorRenderer. --- .../jet/resolve/DescriptorRenderer.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index aef7c264b8c..09992aced60 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -381,7 +381,20 @@ public class DescriptorRenderer implements Renderer { @Override public Void visitClassDescriptor(ClassDescriptor descriptor, StringBuilder builder) { - String keyword = descriptor.getKind() == ClassKind.TRAIT ? "trait" : "class"; + String keyword; + switch (descriptor.getKind()) { + case TRAIT: + keyword = "trait"; + break; + case ENUM_CLASS: + keyword = "enum class"; + break; + case OBJECT: + keyword = "object"; + break; + default: + keyword = "class"; + } renderClassDescriptor(descriptor, builder, keyword); return super.visitClassDescriptor(descriptor, builder); } @@ -390,9 +403,12 @@ public class DescriptorRenderer implements Renderer { if (descriptor.getKind() != ClassKind.TRAIT) { renderModality(descriptor.getModality(), builder); } - builder.append(renderKeyword(keyword)).append(" "); - renderName(descriptor, builder); - renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder); + builder.append(renderKeyword(keyword)); + if (descriptor.getKind() != ClassKind.OBJECT) { + builder.append(" "); + renderName(descriptor, builder); + renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder); + } if (!descriptor.equals(JetStandardClasses.getNothing())) { Collection supertypes = descriptor.getTypeConstructor().getSupertypes(); if (!supertypes.isEmpty()) { From 126c3d00338e107bf1f8676bdd4b2f83252972e3 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sat, 10 Mar 2012 20:29:24 +0400 Subject: [PATCH 31/43] Added class objects support in JetDecompiledData. --- .../plugin/libraries/JetDecompiledData.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java index bfd4e79ffa9..4a5044daed2 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -176,8 +176,6 @@ public class JetDecompiledData { private void appendDescriptor(StringBuilder builder, DeclarationDescriptor descriptor, BindingContext bindingContext, String indent) { String decompiledComment = "/* " + PsiBundle.message("psi.decompiled.method.body") + " */"; - builder.append(indent); - int startOffset = builder.length(); builder.append(DescriptorRenderer.COMPACT.render(descriptor)); int endOffset = builder.length(); @@ -189,15 +187,23 @@ public class JetDecompiledData { builder.append(" ").append(decompiledComment); } else if (descriptor instanceof ClassDescriptor) { builder.append(" {\n"); + ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; boolean firstPassed = false; - for (DeclarationDescriptor member : ((ClassDescriptor) descriptor).getDefaultType().getMemberScope().getAllDescriptors()) { + String subindent = indent + " "; + if (classDescriptor.getClassObjectDescriptor() != null) { + firstPassed = true; + builder.append(subindent).append("class "); + appendDescriptor(builder, classDescriptor.getClassObjectDescriptor(), bindingContext, subindent); + } + for (DeclarationDescriptor member : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) { if (member.getContainingDeclaration() == descriptor) { if (firstPassed) { builder.append("\n"); } else { firstPassed = true; } - appendDescriptor(builder, member, bindingContext, indent + " "); + builder.append(subindent); + appendDescriptor(builder, member, bindingContext, subindent); } } builder.append(indent).append("}"); @@ -206,7 +212,9 @@ public class JetDecompiledData { builder.append("\n"); PsiElement clsMember = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); - myClsMembersToRanges.put(clsMember, new TextRange(startOffset, endOffset)); + if (clsMember != null) { + myClsMembersToRanges.put(clsMember, new TextRange(startOffset, endOffset)); + } } private static boolean hasAnnotation(PsiModifierListOwner modifierListOwner, String qualifiedName) { From f7c969de36ae2465f43c5aeb42f01d4e2145cb9a Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sat, 10 Mar 2012 20:32:43 +0400 Subject: [PATCH 32/43] removed unnecessary ": jet.Any" in class declarations. --- .../src/org/jetbrains/jet/resolve/DescriptorRenderer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 09992aced60..d8b17b08a6f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -411,7 +411,8 @@ public class DescriptorRenderer implements Renderer { } if (!descriptor.equals(JetStandardClasses.getNothing())) { Collection supertypes = descriptor.getTypeConstructor().getSupertypes(); - if (!supertypes.isEmpty()) { + if (supertypes.isEmpty() || supertypes.size() == 1 && JetStandardClasses.isAny(supertypes.iterator().next())) { + } else { builder.append(" : "); for (Iterator iterator = supertypes.iterator(); iterator.hasNext(); ) { JetType supertype = iterator.next(); From 11085c22505204bde55c711a54603c1f37bd8ba0 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sun, 11 Mar 2012 16:54:06 +0400 Subject: [PATCH 33/43] Removed unnecessary /*compiled code*/ marks from abstract members. --- .../jet/plugin/libraries/JetDecompiledData.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java index 4a5044daed2..791e514c365 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -180,11 +180,17 @@ public class JetDecompiledData { builder.append(DescriptorRenderer.COMPACT.render(descriptor)); int endOffset = builder.length(); - if (descriptor instanceof FunctionDescriptor) { - builder.append(" { ").append(decompiledComment).append(" }"); - endOffset = builder.length(); - } else if (descriptor instanceof PropertyDescriptor) { - builder.append(" ").append(decompiledComment); + if (descriptor instanceof FunctionDescriptor || descriptor instanceof PropertyDescriptor) { + if (((CallableMemberDescriptor) descriptor).getModality() != Modality.ABSTRACT) { + if (descriptor instanceof FunctionDescriptor) { + builder.append(" { ").append(decompiledComment).append(" }"); + endOffset = builder.length(); + } else { // descriptor instanceof PropertyDescriptor + if (((PropertyDescriptor) descriptor).getModality() != Modality.ABSTRACT) { + builder.append(" ").append(decompiledComment); + } + } + } } else if (descriptor instanceof ClassDescriptor) { builder.append(" {\n"); ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; From 78dce9d2f28259c6f772c1e92ef9194ff7c41bc4 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sun, 11 Mar 2012 16:57:02 +0400 Subject: [PATCH 34/43] Minor. --- .../jetbrains/jet/plugin/libraries/JetDecompiledData.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java index 791e514c365..09ee4fdb9ce 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -53,6 +53,7 @@ import java.util.Map; public class JetDecompiledData { private static final String JET_CLASS = JetClass.class.getName(); private static final String JET_METHOD = JetMethod.class.getName(); + private static final String DECOMPILED_COMMENT = "/* " + PsiBundle.message("psi.decompiled.method.body") + " */"; private JetFile myJetFile; private String myText; private Map myClsElementsToJetElements = new HashMap(); @@ -174,8 +175,6 @@ public class JetDecompiledData { } private void appendDescriptor(StringBuilder builder, DeclarationDescriptor descriptor, BindingContext bindingContext, String indent) { - String decompiledComment = "/* " + PsiBundle.message("psi.decompiled.method.body") + " */"; - int startOffset = builder.length(); builder.append(DescriptorRenderer.COMPACT.render(descriptor)); int endOffset = builder.length(); @@ -183,11 +182,11 @@ public class JetDecompiledData { if (descriptor instanceof FunctionDescriptor || descriptor instanceof PropertyDescriptor) { if (((CallableMemberDescriptor) descriptor).getModality() != Modality.ABSTRACT) { if (descriptor instanceof FunctionDescriptor) { - builder.append(" { ").append(decompiledComment).append(" }"); + builder.append(" { ").append(DECOMPILED_COMMENT).append(" }"); endOffset = builder.length(); } else { // descriptor instanceof PropertyDescriptor if (((PropertyDescriptor) descriptor).getModality() != Modality.ABSTRACT) { - builder.append(" ").append(decompiledComment); + builder.append(" ").append(DECOMPILED_COMMENT); } } } From 95f859d00ddf789c7418c5e2a3d1e831cbbac5b3 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sun, 11 Mar 2012 18:44:41 +0400 Subject: [PATCH 35/43] Refactored JetDecompiledData: extracted DecompiledDataFactory. --- .../libraries/DecompiledDataFactory.java | 196 ++++++++++++++++++ .../JetContentBasedFileSubstitutor.java | 3 +- .../plugin/libraries/JetDecompiledData.java | 175 +--------------- .../JetDummyClassFileViewProvider.java | 2 +- 4 files changed, 204 insertions(+), 172 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java new file mode 100644 index 00000000000..d6f4005f760 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java @@ -0,0 +1,196 @@ +/* + * Copyright 2000-2012 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.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.impl.compiled.ClsAnnotationImpl; +import com.intellij.psi.impl.compiled.ClsElementImpl; +import com.intellij.psi.impl.compiled.ClsFileImpl; +import com.intellij.psi.util.PsiTreeUtil; +import jet.runtime.typeinfo.JetClass; +import jet.runtime.typeinfo.JetMethod; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.JetSemanticServices; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; +import org.jetbrains.jet.resolve.DescriptorRenderer; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Evgeny Gerashchenko + * @since 3/11/12 + */ +class DecompiledDataFactory { + private static final String JET_CLASS = JetClass.class.getName(); + private static final String JET_METHOD = JetMethod.class.getName(); + private static final String DECOMPILED_COMMENT = "/* " + PsiBundle.message("psi.decompiled.method.body") + " */"; + + private StringBuilder myBuilder = new StringBuilder(); + private ClsFileImpl myClsFile; + private BindingContext myBindingContext; + private final Map myClsMembersToRanges = new HashMap(); + + private Map myClsElementsToJetElements = new HashMap(); + private JavaDescriptorResolver myJavaDescriptorResolver; + + private DecompiledDataFactory(ClsFileImpl clsFile) { + myClsFile = clsFile; + Project project = myClsFile.getProject(); + JavaSemanticServices jss = new JavaSemanticServices( + project, + JetSemanticServices.createSemanticServices(project), + new BindingTraceContext()); + myBindingContext = jss.getTrace().getBindingContext(); + myJavaDescriptorResolver = jss.getDescriptorResolver(); + } + + @NotNull + static JetDecompiledData createDecompiledData(@NotNull ClsFileImpl clsFile) { + return new DecompiledDataFactory(clsFile).build(); + } + + private JetDecompiledData build() { + myBuilder.append(PsiBundle.message("psi.decompiled.text.header")); + myBuilder.append("\n\n"); + + String packageName = myClsFile.getPackageName(); + if (packageName.length() > 0) { + myBuilder.append("package ").append(packageName).append("\n\n"); + } + + PsiClass psiClass = myClsFile.getClasses()[0]; + + if (isKotlinNamespaceClass(psiClass)) { + NamespaceDescriptor nd = myJavaDescriptorResolver.resolveNamespace(packageName); + + if (nd != null) { + for (DeclarationDescriptor member : nd.getMemberScope().getAllDescriptors()) { + if (member instanceof ClassDescriptor || member instanceof NamespaceDescriptor) { + continue; + } + appendDescriptor(member, ""); + myBuilder.append("\n"); + } + } + } else { + ClassDescriptor cd = myJavaDescriptorResolver.resolveClass(psiClass); + if (cd != null) { + appendDescriptor(cd, ""); + } + } + + JetFile jetFile = JetDummyClassFileViewProvider.createJetFile(myClsFile.getManager(), myClsFile.getVirtualFile(), myBuilder.toString()); + for (Map.Entry clsMemberToRange : myClsMembersToRanges.entrySet()) { + PsiElement clsMember = clsMemberToRange.getKey(); + assert clsMember instanceof ClsElementImpl; + + TextRange range = clsMemberToRange.getValue(); + JetDeclaration jetDeclaration = PsiTreeUtil.findElementOfClassAtRange(jetFile, range.getStartOffset(), range.getEndOffset(), JetDeclaration.class); + assert jetDeclaration != null; + myClsElementsToJetElements.put((ClsElementImpl) clsMember, jetDeclaration); + } + + return new JetDecompiledData(jetFile, myClsElementsToJetElements); + } + + private void appendDescriptor(DeclarationDescriptor descriptor, String indent) { + int startOffset = myBuilder.length(); + myBuilder.append(DescriptorRenderer.COMPACT.render(descriptor)); + int endOffset = myBuilder.length(); + + if (descriptor instanceof FunctionDescriptor || descriptor instanceof PropertyDescriptor) { + if (((CallableMemberDescriptor) descriptor).getModality() != Modality.ABSTRACT) { + if (descriptor instanceof FunctionDescriptor) { + myBuilder.append(" { ").append(DECOMPILED_COMMENT).append(" }"); + endOffset = myBuilder.length(); + } else { // descriptor instanceof PropertyDescriptor + if (((PropertyDescriptor) descriptor).getModality() != Modality.ABSTRACT) { + myBuilder.append(" ").append(DECOMPILED_COMMENT); + } + } + } + } else if (descriptor instanceof ClassDescriptor) { + myBuilder.append(" {\n"); + ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; + boolean firstPassed = false; + String subindent = indent + " "; + if (classDescriptor.getClassObjectDescriptor() != null) { + firstPassed = true; + myBuilder.append(subindent).append("class "); + appendDescriptor(classDescriptor.getClassObjectDescriptor(), subindent); + } + for (DeclarationDescriptor member : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) { + if (member.getContainingDeclaration() == descriptor) { + if (firstPassed) { + myBuilder.append("\n"); + } else { + firstPassed = true; + } + myBuilder.append(subindent); + appendDescriptor(member, subindent); + } + } + myBuilder.append(indent).append("}"); + endOffset = myBuilder.length(); + } + + myBuilder.append("\n"); + PsiElement clsMember = myBindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); + if (clsMember != null) { + myClsMembersToRanges.put(clsMember, new TextRange(startOffset, endOffset)); + } + } + + private static boolean hasAnnotation(PsiModifierListOwner modifierListOwner, String qualifiedName) { + PsiModifierList modifierList = modifierListOwner.getModifierList(); + if (modifierList != null) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (annotation instanceof ClsAnnotationImpl) { + if (qualifiedName.equals(annotation.getQualifiedName())) { + return true; + } + } + } + } + return false; + } + + static boolean isKotlinClass(PsiClass psiClass) { + return hasAnnotation(psiClass, JET_CLASS); + } + + static boolean isKotlinNamespaceClass(PsiClass psiClass) { + if (JvmAbi.PACKAGE_CLASS.equals(psiClass.getName()) && !isKotlinClass(psiClass)) { + for (PsiMethod method : psiClass.getMethods()) { + if (hasAnnotation(method, JET_METHOD)) { + return true; + } + } + } + return false; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java index acf14b819b8..d4c47795b9a 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java @@ -25,7 +25,6 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.impl.compiled.ClsFileImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.plugin.JetHighlighter; -import org.jetbrains.jet.plugin.libraries.JetDecompiledData; /** * @author Evgeny Gerashchenko @@ -43,7 +42,7 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc public String obtainFileText(Project project, VirtualFile file) { ClsFileImpl clsFile = JetDecompiledData.getClsFileIfKotlin(project, file); if (clsFile != null) { - return JetDecompiledData.getDecompiledData(clsFile).getText(); + return JetDecompiledData.getDecompiledData(clsFile).getJetFile().getText(); } return ""; } diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java index 09ee4fdb9ce..fa0f6cb8762 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -20,27 +20,14 @@ import com.intellij.ide.highlighter.JavaClassFileType; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.compiled.ClsAnnotationImpl; import com.intellij.psi.impl.compiled.ClsElementImpl; import com.intellij.psi.impl.compiled.ClsFileImpl; -import com.intellij.psi.util.PsiTreeUtil; -import jet.runtime.typeinfo.JetClass; -import jet.runtime.typeinfo.JetMethod; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.JetSemanticServices; -import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingTraceContext; -import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; -import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; -import org.jetbrains.jet.lang.resolve.java.JvmAbi; -import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.HashMap; import java.util.Map; @@ -51,19 +38,15 @@ import java.util.Map; */ @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") public class JetDecompiledData { - private static final String JET_CLASS = JetClass.class.getName(); - private static final String JET_METHOD = JetMethod.class.getName(); - private static final String DECOMPILED_COMMENT = "/* " + PsiBundle.message("psi.decompiled.method.body") + " */"; private JetFile myJetFile; - private String myText; private Map myClsElementsToJetElements = new HashMap(); private static final Object LOCK = new String("decompiled data lock"); private static final Key USER_DATA_KEY = new Key("USER_DATA_KEY"); - private final Map myClsMembersToRanges; - private JetDecompiledData() { - myClsMembersToRanges = new HashMap(); + JetDecompiledData(JetFile jetFile, Map clsElementJetDeclarationMap) { + myJetFile = jetFile; + myClsElementsToJetElements = clsElementJetDeclarationMap; } @NotNull @@ -71,15 +54,11 @@ public class JetDecompiledData { return myJetFile; } - @NotNull - public String getText() { - return myText; - } - public JetDeclaration getJetDeclarationByClsElement(ClsElementImpl clsElement) { return myClsElementsToJetElements.get(clsElement); } + @Deprecated @Nullable public static ClsFileImpl getClsFileIfKotlin(@NotNull Project project, @NotNull VirtualFile vFile) { if (!FileTypeManager.getInstance().isFileOfType(vFile, JavaClassFileType.INSTANCE)) { @@ -94,160 +73,18 @@ public class JetDecompiledData { return null; } PsiClass psiClass = clsFile.getClasses()[0]; - return isKotlinNamespaceClass(psiClass) || isKotlinClass(psiClass) ? clsFile : null; + return DecompiledDataFactory.isKotlinNamespaceClass(psiClass) || DecompiledDataFactory.isKotlinClass(psiClass) ? clsFile : null; } @NotNull public static JetDecompiledData getDecompiledData(@NotNull ClsFileImpl clsFile) { synchronized (LOCK) { if (clsFile.getUserData(USER_DATA_KEY) == null) { - clsFile.putUserData(USER_DATA_KEY, decompileData(clsFile)); + clsFile.putUserData(USER_DATA_KEY, DecompiledDataFactory.createDecompiledData(clsFile)); } JetDecompiledData decompiledData = clsFile.getUserData(USER_DATA_KEY); assert decompiledData != null; return decompiledData; } } - - @NotNull - private static JetDecompiledData decompileData(@NotNull ClsFileImpl clsFile) { - JetDecompiledData result = new JetDecompiledData(); - - Project project = clsFile.getProject(); - result.buildTextAndTree(project, clsFile.getVirtualFile()); - - return result; - } - - - private void buildTextAndTree(Project project, VirtualFile file) { - StringBuilder builder = new StringBuilder(); - - BindingTraceContext trace = new BindingTraceContext(); - JavaSemanticServices jss = new JavaSemanticServices( - project, - JetSemanticServices.createSemanticServices(project), - trace); - PsiManager psiManager = PsiManager.getInstance(project); - ClsFileImpl clsFile = (ClsFileImpl) psiManager.findFile(file); - assert clsFile != null; - builder.append(PsiBundle.message("psi.decompiled.text.header")); - builder.append("\n\n"); - - String packageName = clsFile.getPackageName(); - if (packageName.length() > 0) { - builder.append("package ").append(packageName).append("\n\n"); - } - - PsiClass psiClass = clsFile.getClasses()[0]; - JavaDescriptorResolver jdr = jss.getDescriptorResolver(); - - if (isKotlinNamespaceClass(psiClass)) { - NamespaceDescriptor nd = jdr.resolveNamespace(packageName); - - if (nd != null) { - for (DeclarationDescriptor member : nd.getMemberScope().getAllDescriptors()) { - if (member instanceof ClassDescriptor || member instanceof NamespaceDescriptor) { - continue; - } - appendDescriptor(builder, member, trace.getBindingContext(), ""); - builder.append("\n"); - } - } - } else { - ClassDescriptor cd = jdr.resolveClass(psiClass); - if (cd != null) { - appendDescriptor(builder, cd, trace.getBindingContext(), ""); - } - } - - myText = builder.toString(); - myJetFile = JetDummyClassFileViewProvider.createJetFile(psiManager, file, myText); - for (Map.Entry clsMemberToRange : myClsMembersToRanges.entrySet()) { - PsiElement clsMember = clsMemberToRange.getKey(); - assert clsMember instanceof ClsElementImpl; - - TextRange range = clsMemberToRange.getValue(); - JetDeclaration jetDeclaration = PsiTreeUtil.findElementOfClassAtRange(myJetFile, range.getStartOffset(), range.getEndOffset(), JetDeclaration.class); - assert jetDeclaration != null; - myClsElementsToJetElements.put((ClsElementImpl) clsMember, jetDeclaration); - } - } - - private void appendDescriptor(StringBuilder builder, DeclarationDescriptor descriptor, BindingContext bindingContext, String indent) { - int startOffset = builder.length(); - builder.append(DescriptorRenderer.COMPACT.render(descriptor)); - int endOffset = builder.length(); - - if (descriptor instanceof FunctionDescriptor || descriptor instanceof PropertyDescriptor) { - if (((CallableMemberDescriptor) descriptor).getModality() != Modality.ABSTRACT) { - if (descriptor instanceof FunctionDescriptor) { - builder.append(" { ").append(DECOMPILED_COMMENT).append(" }"); - endOffset = builder.length(); - } else { // descriptor instanceof PropertyDescriptor - if (((PropertyDescriptor) descriptor).getModality() != Modality.ABSTRACT) { - builder.append(" ").append(DECOMPILED_COMMENT); - } - } - } - } else if (descriptor instanceof ClassDescriptor) { - builder.append(" {\n"); - ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; - boolean firstPassed = false; - String subindent = indent + " "; - if (classDescriptor.getClassObjectDescriptor() != null) { - firstPassed = true; - builder.append(subindent).append("class "); - appendDescriptor(builder, classDescriptor.getClassObjectDescriptor(), bindingContext, subindent); - } - for (DeclarationDescriptor member : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) { - if (member.getContainingDeclaration() == descriptor) { - if (firstPassed) { - builder.append("\n"); - } else { - firstPassed = true; - } - builder.append(subindent); - appendDescriptor(builder, member, bindingContext, subindent); - } - } - builder.append(indent).append("}"); - endOffset = builder.length(); - } - - builder.append("\n"); - PsiElement clsMember = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); - if (clsMember != null) { - myClsMembersToRanges.put(clsMember, new TextRange(startOffset, endOffset)); - } - } - - private static boolean hasAnnotation(PsiModifierListOwner modifierListOwner, String qualifiedName) { - PsiModifierList modifierList = modifierListOwner.getModifierList(); - if (modifierList != null) { - for (PsiAnnotation annotation : modifierList.getAnnotations()) { - if (annotation instanceof ClsAnnotationImpl) { - if (qualifiedName.equals(annotation.getQualifiedName())) { - return true; - } - } - } - } - return false; - } - - private static boolean isKotlinClass(PsiClass psiClass) { - return hasAnnotation(psiClass, JET_CLASS); - } - - private static boolean isKotlinNamespaceClass(PsiClass psiClass) { - if (JvmAbi.PACKAGE_CLASS.equals(psiClass.getName()) && !isKotlinClass(psiClass)) { - for (PsiMethod method : psiClass.getMethods()) { - if (hasAnnotation(method, JET_METHOD)) { - return true; - } - } - } - return false; - } } diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java index baa8f2d0354..6348b7be1db 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java @@ -64,7 +64,7 @@ class JetDummyClassFileViewProvider extends UserDataHolderBase implements FileVi @Override @NotNull - public CharSequence getContents() { + public String getContents() { return myText; } From 4151718f6b8729f19869dbcb722cffd6e4703472 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sun, 11 Mar 2012 18:46:17 +0400 Subject: [PATCH 36/43] Replaced JetDecompiledData.getClsFileIfKotlin() with getClsFile() and isKotlinFile() --- .../libraries/JetClsNavigationPolicy.java | 3 +-- .../JetContentBasedFileSubstitutor.java | 7 ++++--- .../jet/plugin/libraries/JetDecompiledData.java | 17 +++++++++++++---- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java index 3a3ca4e3e3d..0a824090c0a 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java @@ -22,7 +22,6 @@ import com.intellij.psi.impl.compiled.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetDeclaration; -import org.jetbrains.jet.plugin.libraries.JetDecompiledData; /** * @author Evgeny Gerashchenko @@ -50,7 +49,7 @@ public class JetClsNavigationPolicy implements ClsCustomNavigationPolicy { @Nullable private static JetDeclaration getJetDeclarationByClsElement(ClsElementImpl clsElement) { VirtualFile virtualFile = clsElement.getContainingFile().getVirtualFile(); - if (virtualFile == null || JetDecompiledData.getClsFileIfKotlin(clsElement.getProject(), virtualFile) == null) { + if (virtualFile == null || !JetDecompiledData.isKotlinFile(clsElement.getProject(), virtualFile)) { return null; } JetDecompiledData decompiledData = JetDecompiledData.getDecompiledData((ClsFileImpl) clsElement.getContainingFile()); diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java index d4c47795b9a..a6c6cff9829 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java @@ -34,14 +34,15 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc @Override public boolean isApplicable(Project project, VirtualFile file) { - return JetDecompiledData.getClsFileIfKotlin(project, file) != null; + return JetDecompiledData.isKotlinFile(project, file); } @NotNull @Override public String obtainFileText(Project project, VirtualFile file) { - ClsFileImpl clsFile = JetDecompiledData.getClsFileIfKotlin(project, file); - if (clsFile != null) { + if (JetDecompiledData.isKotlinFile(project, file)) { + ClsFileImpl clsFile = JetDecompiledData.getClsFile(project, file); + assert clsFile != null; return JetDecompiledData.getDecompiledData(clsFile).getJetFile().getText(); } return ""; diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java index fa0f6cb8762..056e95d215d 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -21,7 +21,9 @@ import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; import com.intellij.psi.impl.compiled.ClsElementImpl; import com.intellij.psi.impl.compiled.ClsFileImpl; import org.jetbrains.annotations.NotNull; @@ -58,9 +60,8 @@ public class JetDecompiledData { return myClsElementsToJetElements.get(clsElement); } - @Deprecated @Nullable - public static ClsFileImpl getClsFileIfKotlin(@NotNull Project project, @NotNull VirtualFile vFile) { + public static ClsFileImpl getClsFile(@NotNull Project project, @NotNull VirtualFile vFile) { if (!FileTypeManager.getInstance().isFileOfType(vFile, JavaClassFileType.INSTANCE)) { return null; } @@ -72,8 +73,16 @@ public class JetDecompiledData { if (clsFile.getClasses().length != 1) { return null; } + return clsFile; + } + + public static boolean isKotlinFile(@NotNull Project project, @NotNull VirtualFile vFile) { + ClsFileImpl clsFile = getClsFile(project, vFile); + if (clsFile == null) { + return false; + } PsiClass psiClass = clsFile.getClasses()[0]; - return DecompiledDataFactory.isKotlinNamespaceClass(psiClass) || DecompiledDataFactory.isKotlinClass(psiClass) ? clsFile : null; + return DecompiledDataFactory.isKotlinNamespaceClass(psiClass) || DecompiledDataFactory.isKotlinClass(psiClass); } @NotNull From a0ea56be3f1733930f7431e8cbc6523031abe7d8 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Mon, 12 Mar 2012 14:02:58 +0400 Subject: [PATCH 37/43] Added LibrariesTest (checking only one decompiled source yet). --- idea/idea.iml | 1 + idea/testData/libraries/AbstractClass.kt | 7 ++ idea/testData/libraries/library/library.kt | 68 ++++++++++++++++ .../jet/plugin/libraries/LibrariesTest.java | 80 +++++++++++++++++++ 4 files changed, 156 insertions(+) create mode 100644 idea/testData/libraries/AbstractClass.kt create mode 100644 idea/testData/libraries/library/library.kt create mode 100644 idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java diff --git a/idea/idea.iml b/idea/idea.iml index 99b26f27f32..14d52a25fbe 100644 --- a/idea/idea.iml +++ b/idea/idea.iml @@ -27,6 +27,7 @@ + diff --git a/idea/testData/libraries/AbstractClass.kt b/idea/testData/libraries/AbstractClass.kt new file mode 100644 index 00000000000..6ad215d3258 --- /dev/null +++ b/idea/testData/libraries/AbstractClass.kt @@ -0,0 +1,7 @@ +// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +abstract class AbstractClass { +} \ No newline at end of file diff --git a/idea/testData/libraries/library/library.kt b/idea/testData/libraries/library/library.kt new file mode 100644 index 00000000000..3b97c6b7252 --- /dev/null +++ b/idea/testData/libraries/library/library.kt @@ -0,0 +1,68 @@ +package testData.libraries + +trait SimpleTrait { +} + +class SimpleClass { +} + +class SimpleTraitImpl : SimpleTrait { +} + +class WithInnerAndObject { + class object { + fun foo() { + } + } + + class MyInner { + trait MyInnerInner { + fun innerInnerMethod() + } + } +} + +class WithTraitClassObject { + class object : SimpleTrait +} + +abstract class AbstractClass { +} + +enum class Color(val rgb : Int) { + RED : Color(0xFF0000) + GREEN : Color(0x00FF00) + BLUE : Color(0x0000FF) +} + +abstract class ClassWithAbstractAndOpenMembers { + abstract fun abstractFun() + open fun openFun() { + } + + abstract val abstractVal : String + open val openVal : String = "" + open val openValWithGetter : String + get() { + return "239" + } + + abstract var abstractVar : String + open var openVar : String = "" + open var openVarWithGetter : String + get() { + return "239" + } + set(value) { + } +} + +fun main(args : Array) { +} + +val globalVal : #(Int, String) = #(239, "239") + +val globalValWithGetter : Long +get() { + return System.currentTimeMillis() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java b/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java new file mode 100644 index 00000000000..964184ca7d7 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2012 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.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.PlatformTestCase; +import org.jetbrains.jet.cli.KotlinCompiler; +import org.jetbrains.jet.plugin.PluginTestCaseBase; + +/** + * @author Evgeny Gerashchenko + * @since 3/11/12 + */ +public class LibrariesTest extends PlatformTestCase { + + private static final String PACKAGE = "testData.libraries"; + private static final String TEST_DATA_PATH = PluginTestCaseBase.getTestDataPathBase() + "/libraries"; + private VirtualFile myLibraryDir; + + public void testAbstractClass() { + doTest(); + } + + private void doTest() { + String testName = getTestName(false); + VirtualFile packageDir = myLibraryDir.findFileByRelativePath(PACKAGE.replace(".", "/")); + assertNotNull(packageDir); + VirtualFile classFile = packageDir.findChild(testName + ".class"); + assertNotNull(classFile); + Document document = FileDocumentManager.getInstance().getDocument(classFile); + assert document != null; + String decompiledText = document.getText(); + assertSameLinesWithFile(TEST_DATA_PATH + "/" + testName + ".kt", decompiledText); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + String libraryDir = FileUtil.getTempDirectory(); + KotlinCompiler.exec("-src", TEST_DATA_PATH + "/library", "-output", libraryDir); + myLibraryDir = LocalFileSystem.getInstance().findFileByPath(libraryDir); + assertNotNull(myLibraryDir); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + ModifiableRootModel moduleModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + + Library.ModifiableModel libraryModel = moduleModel.getModuleLibraryTable().getModifiableModel().createLibrary("myKotlinLib").getModifiableModel(); + libraryModel.addRoot(myLibraryDir, OrderRootType.CLASSES); + libraryModel.commit(); + + moduleModel.commit(); + } + }); + } +} From 09c48ae4405e3ec52ffe025151882cbe28698bf5 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Mon, 12 Mar 2012 14:15:24 +0400 Subject: [PATCH 38/43] Added test cases checking all decompiled files. --- .../ClassWithAbstractAndOpenMembers.kt | 22 +++++++++++++ idea/testData/libraries/Color.kt | 8 +++++ idea/testData/libraries/SimpleClass.kt | 7 ++++ idea/testData/libraries/SimpleTrait.kt | 7 ++++ idea/testData/libraries/SimpleTraitImpl.kt | 7 ++++ idea/testData/libraries/WithInnerAndObject.kt | 16 ++++++++++ .../libraries/WithTraitClassObject.kt | 9 ++++++ idea/testData/libraries/namespace.kt | 7 ++++ .../jet/plugin/libraries/LibrariesTest.java | 32 +++++++++++++++++++ 9 files changed, 115 insertions(+) create mode 100644 idea/testData/libraries/ClassWithAbstractAndOpenMembers.kt create mode 100644 idea/testData/libraries/Color.kt create mode 100644 idea/testData/libraries/SimpleClass.kt create mode 100644 idea/testData/libraries/SimpleTrait.kt create mode 100644 idea/testData/libraries/SimpleTraitImpl.kt create mode 100644 idea/testData/libraries/WithInnerAndObject.kt create mode 100644 idea/testData/libraries/WithTraitClassObject.kt create mode 100644 idea/testData/libraries/namespace.kt diff --git a/idea/testData/libraries/ClassWithAbstractAndOpenMembers.kt b/idea/testData/libraries/ClassWithAbstractAndOpenMembers.kt new file mode 100644 index 00000000000..3b3f87f630c --- /dev/null +++ b/idea/testData/libraries/ClassWithAbstractAndOpenMembers.kt @@ -0,0 +1,22 @@ +// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +abstract class ClassWithAbstractAndOpenMembers { + abstract fun abstractFun() : Unit + + open fun openFun() : Unit { /* compiled code */ } + + abstract val abstractVal : jet.String + + open val openVal : jet.String /* compiled code */ + + open val openValWithGetter : jet.String /* compiled code */ + + abstract var abstractVar : jet.String + + open var openVar : jet.String /* compiled code */ + + open var openVarWithGetter : jet.String /* compiled code */ +} diff --git a/idea/testData/libraries/Color.kt b/idea/testData/libraries/Color.kt new file mode 100644 index 00000000000..42977e16b4c --- /dev/null +++ b/idea/testData/libraries/Color.kt @@ -0,0 +1,8 @@ +// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +class Color { + val rgb : jet.Int /* compiled code */ +} diff --git a/idea/testData/libraries/SimpleClass.kt b/idea/testData/libraries/SimpleClass.kt new file mode 100644 index 00000000000..518ff14ad8d --- /dev/null +++ b/idea/testData/libraries/SimpleClass.kt @@ -0,0 +1,7 @@ +// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +class SimpleClass { +} diff --git a/idea/testData/libraries/SimpleTrait.kt b/idea/testData/libraries/SimpleTrait.kt new file mode 100644 index 00000000000..7c928aa062f --- /dev/null +++ b/idea/testData/libraries/SimpleTrait.kt @@ -0,0 +1,7 @@ +// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +trait SimpleTrait { +} diff --git a/idea/testData/libraries/SimpleTraitImpl.kt b/idea/testData/libraries/SimpleTraitImpl.kt new file mode 100644 index 00000000000..ab626c6ad59 --- /dev/null +++ b/idea/testData/libraries/SimpleTraitImpl.kt @@ -0,0 +1,7 @@ +// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +class SimpleTraitImpl : testData.libraries.SimpleTrait { +} diff --git a/idea/testData/libraries/WithInnerAndObject.kt b/idea/testData/libraries/WithInnerAndObject.kt new file mode 100644 index 00000000000..0db42b07e4b --- /dev/null +++ b/idea/testData/libraries/WithInnerAndObject.kt @@ -0,0 +1,16 @@ +// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +class WithInnerAndObject { + class object { + fun foo() : Unit { /* compiled code */ } + } + + class MyInner { + trait MyInnerInner { + abstract fun innerInnerMethod() : Unit + } + } +} diff --git a/idea/testData/libraries/WithTraitClassObject.kt b/idea/testData/libraries/WithTraitClassObject.kt new file mode 100644 index 00000000000..9292180ad5a --- /dev/null +++ b/idea/testData/libraries/WithTraitClassObject.kt @@ -0,0 +1,9 @@ +// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +class WithTraitClassObject { + class object : testData.libraries.SimpleTrait { + } +} diff --git a/idea/testData/libraries/namespace.kt b/idea/testData/libraries/namespace.kt new file mode 100644 index 00000000000..83f103921f2 --- /dev/null +++ b/idea/testData/libraries/namespace.kt @@ -0,0 +1,7 @@ +// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +fun main(val args : jet.Array) : Unit { /* compiled code */ } + diff --git a/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java b/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java index 964184ca7d7..096c0bc3744 100644 --- a/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java @@ -44,6 +44,38 @@ public class LibrariesTest extends PlatformTestCase { doTest(); } + public void testClassWithAbstractAndOpenMembers() { + doTest(); + } + + public void testColor() { + doTest(); + } + + public void testnamespace() { + doTest(); + } + + public void testSimpleClass() { + doTest(); + } + + public void testSimpleTrait() { + doTest(); + } + + public void testSimpleTraitImpl() { + doTest(); + } + + public void testWithInnerAndObject() { + doTest(); + } + + public void testWithTraitClassObject() { + doTest(); + } + private void doTest() { String testName = getTestName(false); VirtualFile packageDir = myLibraryDir.findFileByRelativePath(PACKAGE.replace(".", "/")); From 128d074532d6402fd3446d173efa78b9efefee08 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Mon, 12 Mar 2012 14:55:43 +0400 Subject: [PATCH 39/43] Moved WordSelectionTest to jet.plugin package. --- .../tests/org/jetbrains/jet/{ => plugin}/WordSelectionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename idea/tests/org/jetbrains/jet/{ => plugin}/WordSelectionTest.java (98%) diff --git a/idea/tests/org/jetbrains/jet/WordSelectionTest.java b/idea/tests/org/jetbrains/jet/plugin/WordSelectionTest.java similarity index 98% rename from idea/tests/org/jetbrains/jet/WordSelectionTest.java rename to idea/tests/org/jetbrains/jet/plugin/WordSelectionTest.java index 7ffd03b477d..e5863f8f1a6 100644 --- a/idea/tests/org/jetbrains/jet/WordSelectionTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/WordSelectionTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.jet; +package org.jetbrains.jet.plugin; import com.intellij.testFramework.fixtures.CodeInsightTestUtil; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; From f4eba40f4595e2fcd41fef118679c797ca571b6b Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Mon, 12 Mar 2012 15:59:07 +0400 Subject: [PATCH 40/43] Added checks for navigation elements for cls members. --- .../plugin/libraries/JetDecompiledData.java | 7 ++ idea/testData/libraries/AbstractClass.kt | 4 +- .../ClassWithAbstractAndOpenMembers.kt | 20 +++--- idea/testData/libraries/Color.kt | 6 +- idea/testData/libraries/SimpleClass.kt | 4 +- idea/testData/libraries/SimpleTrait.kt | 4 +- idea/testData/libraries/SimpleTraitImpl.kt | 4 +- idea/testData/libraries/WithInnerAndObject.kt | 16 ++--- .../libraries/WithTraitClassObject.kt | 4 +- idea/testData/libraries/namespace.kt | 2 +- .../jet/plugin/libraries/LibrariesTest.java | 70 +++++++++++++++++-- 11 files changed, 103 insertions(+), 38 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java index 056e95d215d..dc9d539bad5 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -28,6 +28,7 @@ import com.intellij.psi.impl.compiled.ClsElementImpl; import com.intellij.psi.impl.compiled.ClsFileImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; @@ -41,6 +42,7 @@ import java.util.Map; @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") public class JetDecompiledData { private JetFile myJetFile; + private Map myClsElementsToJetElements = new HashMap(); private static final Object LOCK = new String("decompiled data lock"); @@ -96,4 +98,9 @@ public class JetDecompiledData { return decompiledData; } } + + @TestOnly + Map getClsElementsToJetElements() { + return myClsElementsToJetElements; + } } diff --git a/idea/testData/libraries/AbstractClass.kt b/idea/testData/libraries/AbstractClass.kt index 6ad215d3258..33cbc85ca07 100644 --- a/idea/testData/libraries/AbstractClass.kt +++ b/idea/testData/libraries/AbstractClass.kt @@ -3,5 +3,5 @@ package testData.libraries -abstract class AbstractClass { -} \ No newline at end of file +[abstract class AbstractClass { +}] \ No newline at end of file diff --git a/idea/testData/libraries/ClassWithAbstractAndOpenMembers.kt b/idea/testData/libraries/ClassWithAbstractAndOpenMembers.kt index 3b3f87f630c..b2c911f2cf0 100644 --- a/idea/testData/libraries/ClassWithAbstractAndOpenMembers.kt +++ b/idea/testData/libraries/ClassWithAbstractAndOpenMembers.kt @@ -3,20 +3,20 @@ package testData.libraries -abstract class ClassWithAbstractAndOpenMembers { - abstract fun abstractFun() : Unit +[abstract class ClassWithAbstractAndOpenMembers { + [abstract fun abstractFun() : Unit] - open fun openFun() : Unit { /* compiled code */ } + [open fun openFun() : Unit { /* compiled code */ }] - abstract val abstractVal : jet.String + [abstract val abstractVal : jet.String] - open val openVal : jet.String /* compiled code */ + [open val openVal : jet.String] /* compiled code */ - open val openValWithGetter : jet.String /* compiled code */ + [open val openValWithGetter : jet.String] /* compiled code */ - abstract var abstractVar : jet.String + [abstract var abstractVar : jet.String] - open var openVar : jet.String /* compiled code */ + [open var openVar : jet.String] /* compiled code */ - open var openVarWithGetter : jet.String /* compiled code */ -} + [open var openVarWithGetter : jet.String] /* compiled code */ +}] diff --git a/idea/testData/libraries/Color.kt b/idea/testData/libraries/Color.kt index 42977e16b4c..1e5516ba4ea 100644 --- a/idea/testData/libraries/Color.kt +++ b/idea/testData/libraries/Color.kt @@ -3,6 +3,6 @@ package testData.libraries -class Color { - val rgb : jet.Int /* compiled code */ -} +[class Color { + [val rgb : jet.Int] /* compiled code */ +}] diff --git a/idea/testData/libraries/SimpleClass.kt b/idea/testData/libraries/SimpleClass.kt index 518ff14ad8d..60528a70a69 100644 --- a/idea/testData/libraries/SimpleClass.kt +++ b/idea/testData/libraries/SimpleClass.kt @@ -3,5 +3,5 @@ package testData.libraries -class SimpleClass { -} +[class SimpleClass { +}] diff --git a/idea/testData/libraries/SimpleTrait.kt b/idea/testData/libraries/SimpleTrait.kt index 7c928aa062f..d25fc5a61ec 100644 --- a/idea/testData/libraries/SimpleTrait.kt +++ b/idea/testData/libraries/SimpleTrait.kt @@ -3,5 +3,5 @@ package testData.libraries -trait SimpleTrait { -} +[trait SimpleTrait { +}] diff --git a/idea/testData/libraries/SimpleTraitImpl.kt b/idea/testData/libraries/SimpleTraitImpl.kt index ab626c6ad59..8c4007af99f 100644 --- a/idea/testData/libraries/SimpleTraitImpl.kt +++ b/idea/testData/libraries/SimpleTraitImpl.kt @@ -3,5 +3,5 @@ package testData.libraries -class SimpleTraitImpl : testData.libraries.SimpleTrait { -} +[class SimpleTraitImpl : testData.libraries.SimpleTrait { +}] diff --git a/idea/testData/libraries/WithInnerAndObject.kt b/idea/testData/libraries/WithInnerAndObject.kt index 0db42b07e4b..4d788cd595e 100644 --- a/idea/testData/libraries/WithInnerAndObject.kt +++ b/idea/testData/libraries/WithInnerAndObject.kt @@ -3,14 +3,14 @@ package testData.libraries -class WithInnerAndObject { +[class WithInnerAndObject { class object { - fun foo() : Unit { /* compiled code */ } + [fun foo() : Unit { /* compiled code */ }] } - class MyInner { - trait MyInnerInner { - abstract fun innerInnerMethod() : Unit - } - } -} + [class MyInner { + [trait MyInnerInner { + [abstract fun innerInnerMethod() : Unit] + }] + }] +}] diff --git a/idea/testData/libraries/WithTraitClassObject.kt b/idea/testData/libraries/WithTraitClassObject.kt index 9292180ad5a..4529fc325bc 100644 --- a/idea/testData/libraries/WithTraitClassObject.kt +++ b/idea/testData/libraries/WithTraitClassObject.kt @@ -3,7 +3,7 @@ package testData.libraries -class WithTraitClassObject { +[class WithTraitClassObject { class object : testData.libraries.SimpleTrait { } -} +}] diff --git a/idea/testData/libraries/namespace.kt b/idea/testData/libraries/namespace.kt index 83f103921f2..405a7414dd9 100644 --- a/idea/testData/libraries/namespace.kt +++ b/idea/testData/libraries/namespace.kt @@ -3,5 +3,5 @@ package testData.libraries -fun main(val args : jet.Array) : Unit { /* compiled code */ } +[fun main(val args : jet.Array) : Unit { /* compiled code */ }] diff --git a/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java b/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java index 096c0bc3744..3dd194c0784 100644 --- a/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java @@ -23,13 +23,21 @@ import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.compiled.ClsElementImpl; +import com.intellij.psi.impl.compiled.ClsFileImpl; import com.intellij.testFramework.PlatformTestCase; import org.jetbrains.jet.cli.KotlinCompiler; +import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.plugin.PluginTestCaseBase; +import java.util.Map; + /** * @author Evgeny Gerashchenko * @since 3/11/12 @@ -39,6 +47,7 @@ public class LibrariesTest extends PlatformTestCase { private static final String PACKAGE = "testData.libraries"; private static final String TEST_DATA_PATH = PluginTestCaseBase.getTestDataPathBase() + "/libraries"; private VirtualFile myLibraryDir; + private VirtualFile myClassFile; public void testAbstractClass() { doTest(); @@ -77,15 +86,64 @@ public class LibrariesTest extends PlatformTestCase { } private void doTest() { - String testName = getTestName(false); + myClassFile = getClassFile(); + + Map map = getDecompiledData(myClassFile).getClsElementsToJetElements(); + checkNavigationElements(map); + String decompiledTextWithMarks = getDecompiledTextWithMarks(map); + + assertSameLinesWithFile(TEST_DATA_PATH + "/" + getTestName(false) + ".kt", decompiledTextWithMarks); + } + + private String getDecompiledTextWithMarks(Map map) { + String decompiledText = getDecompiledText(); + + int[] openings = new int[decompiledText.length() + 1]; + int[] closings = new int[decompiledText.length() + 1]; + for (JetDeclaration jetDeclaration : map.values()) { + TextRange textRange = jetDeclaration.getTextRange(); + openings[textRange.getStartOffset()]++; + closings[textRange.getEndOffset()]++; + } + + StringBuilder result = new StringBuilder(); + for (int i = 0; i <= decompiledText.length(); i++) { + result.append(StringUtil.repeat("]", closings[i])); + result.append(StringUtil.repeat("[", openings[i])); + if (i < decompiledText.length()) { + result.append(decompiledText.charAt(i)); + } + } + return result.toString(); + } + + private String getDecompiledText() { + Document document = FileDocumentManager.getInstance().getDocument(myClassFile); + assertNotNull(document); + return document.getText(); + } + + private JetDecompiledData getDecompiledData(VirtualFile classFile) { + PsiFile classPsiFile = getPsiManager().findFile(classFile); + assertInstanceOf(classPsiFile, ClsFileImpl.class); + ClsFileImpl clsFile = (ClsFileImpl) classPsiFile; + return JetDecompiledData.getDecompiledData(clsFile); + } + + private void checkNavigationElements(Map map) { + PsiFile classPsiFile = getPsiManager().findFile(myClassFile); + for (Map.Entry clsToJet : map.entrySet()) { + assertSame(classPsiFile, clsToJet.getKey().getContainingFile()); + assertSame(clsToJet.getValue(), clsToJet.getKey().getNavigationElement()); + } + } + + private VirtualFile getClassFile() { VirtualFile packageDir = myLibraryDir.findFileByRelativePath(PACKAGE.replace(".", "/")); assertNotNull(packageDir); - VirtualFile classFile = packageDir.findChild(testName + ".class"); + VirtualFile classFile = packageDir.findChild(getTestName(false) + ".class"); assertNotNull(classFile); - Document document = FileDocumentManager.getInstance().getDocument(classFile); - assert document != null; - String decompiledText = document.getText(); - assertSameLinesWithFile(TEST_DATA_PATH + "/" + testName + ".kt", decompiledText); + return classFile; } @Override From 29662cdb1bc46e2dec2b664ffe5486f52f4ac0c2 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Mon, 12 Mar 2012 16:21:17 +0400 Subject: [PATCH 41/43] Fixed JetFunctionParameterInfoTest. Replaced Int with jet.Int, Boolean with jet.Boolean, etc in test data. --- .../functionParameterInfo/InheritedFunctions.kt | 4 ++-- .../functionParameterInfo/InheritedWithCurrentFunctions.kt | 6 +++--- .../functionParameterInfo/NamedAndDefaultParameter.kt | 4 ++-- .../parameterInfo/functionParameterInfo/NamedParameter.kt | 4 ++-- .../parameterInfo/functionParameterInfo/NamedParameter2.kt | 4 ++-- .../parameterInfo/functionParameterInfo/NotGreen.kt | 4 ++-- .../parameterInfo/functionParameterInfo/NullableTypeCall.kt | 4 ++-- .../testData/parameterInfo/functionParameterInfo/Println.kt | 4 ++-- idea/testData/parameterInfo/functionParameterInfo/Simple.kt | 2 +- .../functionParameterInfo/SimpleConstructor.kt | 2 +- .../functionParameterInfo/SuperConstructorCall.kt | 2 +- .../parameterInfo/functionParameterInfo/TwoFunctions.kt | 4 ++-- .../parameterInfo/functionParameterInfo/TwoFunctionsGrey.kt | 4 ++-- 13 files changed, 24 insertions(+), 24 deletions(-) diff --git a/idea/testData/parameterInfo/functionParameterInfo/InheritedFunctions.kt b/idea/testData/parameterInfo/functionParameterInfo/InheritedFunctions.kt index 126ef03b06c..48d26264ddc 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/InheritedFunctions.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/InheritedFunctions.kt @@ -9,6 +9,6 @@ class B(): A(5) { } } /* -Text: (x: Int), Disabled: true, Strikeout: false, Green: false -Text: (x: Int, y: Boolean), Disabled: false, Strikeout: false, Green: true +Text: (x: jet.Int), Disabled: true, Strikeout: false, Green: false +Text: (x: jet.Int, y: jet.Boolean), Disabled: false, Strikeout: false, Green: true */ \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/InheritedWithCurrentFunctions.kt b/idea/testData/parameterInfo/functionParameterInfo/InheritedWithCurrentFunctions.kt index d6b13f9c5be..83c4d68d54a 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/InheritedWithCurrentFunctions.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/InheritedWithCurrentFunctions.kt @@ -9,7 +9,7 @@ class B(): A(5) { } } /* -Text: (x: Int), Disabled: true, Strikeout: false, Green: false -Text: (x: Int, y: Boolean), Disabled: false, Strikeout: false, Green: true -Text: (x: Int, y: Boolean, z: String), Disabled: false, Strikeout: false, Green: false +Text: (x: jet.Int), Disabled: true, Strikeout: false, Green: false +Text: (x: jet.Int, y: jet.Boolean), Disabled: false, Strikeout: false, Green: true +Text: (x: jet.Int, y: jet.Boolean, z: jet.String), Disabled: false, Strikeout: false, Green: false */ \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/NamedAndDefaultParameter.kt b/idea/testData/parameterInfo/functionParameterInfo/NamedAndDefaultParameter.kt index af69b172479..8abdc1f57ea 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/NamedAndDefaultParameter.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/NamedAndDefaultParameter.kt @@ -7,6 +7,6 @@ open class A(x: Int) { } } /* -Text: ([x: Int]), Disabled: false, Strikeout: false, Green: false -Text: ([y: Boolean = true], [x: Int], [z: Long = 1234567...]), Disabled: false, Strikeout: false, Green: true +Text: ([x: jet.Int]), Disabled: false, Strikeout: false, Green: false +Text: ([y: jet.Boolean = true], [x: jet.Int], [z: jet.Long = 1234567...]), Disabled: false, Strikeout: false, Green: true */ \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/NamedParameter.kt b/idea/testData/parameterInfo/functionParameterInfo/NamedParameter.kt index 682fb09d4e7..a7954d7a227 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/NamedParameter.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/NamedParameter.kt @@ -7,6 +7,6 @@ open class A(x: Int) { } } /* -Text: ([x: Int]), Disabled: true, Strikeout: false, Green: false -Text: ([x: Int], [y: Boolean]), Disabled: false, Strikeout: false, Green: true +Text: ([x: jet.Int]), Disabled: true, Strikeout: false, Green: false +Text: ([x: jet.Int], [y: jet.Boolean]), Disabled: false, Strikeout: false, Green: true */ \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/NamedParameter2.kt b/idea/testData/parameterInfo/functionParameterInfo/NamedParameter2.kt index 28aeba1cd81..53a28110451 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/NamedParameter2.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/NamedParameter2.kt @@ -7,6 +7,6 @@ open class A(x: Int) { } } /* -Text: ([x: Int]), Disabled: false, Strikeout: false, Green: false -Text: ([y: Boolean], [x: Int]), Disabled: false, Strikeout: false, Green: true +Text: ([x: jet.Int]), Disabled: false, Strikeout: false, Green: false +Text: ([y: jet.Boolean], [x: jet.Int]), Disabled: false, Strikeout: false, Green: true */ \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/NotGreen.kt b/idea/testData/parameterInfo/functionParameterInfo/NotGreen.kt index a9f3d171fb2..db69ffae91f 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/NotGreen.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/NotGreen.kt @@ -7,6 +7,6 @@ open class A(x: Int) { } } /* -Text: (x: Int), Disabled: false, Strikeout: false, Green: false -Text: (x: Int, y: Boolean), Disabled: false, Strikeout: false, Green: false +Text: (x: jet.Int), Disabled: false, Strikeout: false, Green: false +Text: (x: jet.Int, y: jet.Boolean), Disabled: false, Strikeout: false, Green: false */ \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/NullableTypeCall.kt b/idea/testData/parameterInfo/functionParameterInfo/NullableTypeCall.kt index 2ce1311500d..5010ccf4ae8 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/NullableTypeCall.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/NullableTypeCall.kt @@ -14,6 +14,6 @@ fun f() { } } /* -Text: (x: Int), Disabled: false, Strikeout: false, Green: false -Text: (x: Int, y: Int), Disabled: false, Strikeout: false, Green: false +Text: (x: jet.Int), Disabled: false, Strikeout: false, Green: false +Text: (x: jet.Int, y: jet.Int), Disabled: false, Strikeout: false, Green: false */ \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/Println.kt b/idea/testData/parameterInfo/functionParameterInfo/Println.kt index ae4f653f6e5..91f328de2ae 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/Println.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/Println.kt @@ -9,6 +9,6 @@ open class A(x: Int) { } /* Text: (), Disabled: false, Strikeout: false, Green: true -Text: (x: Boolean), Disabled: false, Strikeout: false, Green: false -Text: (x: String), Disabled: false, Strikeout: false, Green: false +Text: (x: jet.Boolean), Disabled: false, Strikeout: false, Green: false +Text: (x: jet.String), Disabled: false, Strikeout: false, Green: false */ \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/Simple.kt b/idea/testData/parameterInfo/functionParameterInfo/Simple.kt index 99837866097..e848ca83da6 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/Simple.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/Simple.kt @@ -5,4 +5,4 @@ open class A(x: Int) { m(1, false) } } -//Text: (x: Int, y: Boolean), Disabled: false, Strikeout: false, Green: true \ No newline at end of file +//Text: (x: jet.Int, y: jet.Boolean), Disabled: false, Strikeout: false, Green: true \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/SimpleConstructor.kt b/idea/testData/parameterInfo/functionParameterInfo/SimpleConstructor.kt index 6ecc459bf25..a7b9565517c 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/SimpleConstructor.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/SimpleConstructor.kt @@ -6,4 +6,4 @@ class B(): A(5) { A(3) } } -//Text: (x: Int), Disabled: false, Strikeout: false, Green: true \ No newline at end of file +//Text: (x: jet.Int), Disabled: false, Strikeout: false, Green: true \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/SuperConstructorCall.kt b/idea/testData/parameterInfo/functionParameterInfo/SuperConstructorCall.kt index 194074c402a..3db8a746d0c 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/SuperConstructorCall.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/SuperConstructorCall.kt @@ -6,4 +6,4 @@ class B(): A(5) { A(3) } } -//Text: (x: Int), Disabled: false, Strikeout: false, Green: true \ No newline at end of file +//Text: (x: jet.Int), Disabled: false, Strikeout: false, Green: true \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/TwoFunctions.kt b/idea/testData/parameterInfo/functionParameterInfo/TwoFunctions.kt index 7aa8d4ebad3..de55c422251 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/TwoFunctions.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/TwoFunctions.kt @@ -7,6 +7,6 @@ open class A(x: Int) { } } /* -Text: (x: Int), Disabled: false, Strikeout: false, Green: false -Text: (x: Int, y: Boolean), Disabled: false, Strikeout: false, Green: true +Text: (x: jet.Int), Disabled: false, Strikeout: false, Green: false +Text: (x: jet.Int, y: jet.Boolean), Disabled: false, Strikeout: false, Green: true */ \ No newline at end of file diff --git a/idea/testData/parameterInfo/functionParameterInfo/TwoFunctionsGrey.kt b/idea/testData/parameterInfo/functionParameterInfo/TwoFunctionsGrey.kt index e18c637d38d..3bbd4e7170c 100644 --- a/idea/testData/parameterInfo/functionParameterInfo/TwoFunctionsGrey.kt +++ b/idea/testData/parameterInfo/functionParameterInfo/TwoFunctionsGrey.kt @@ -7,6 +7,6 @@ open class A(x: Int) { } } /* -Text: (x: Int), Disabled: true, Strikeout: false, Green: false -Text: (x: Int, y: Boolean), Disabled: false, Strikeout: false, Green: true +Text: (x: jet.Int), Disabled: true, Strikeout: false, Green: false +Text: (x: jet.Int, y: jet.Boolean), Disabled: false, Strikeout: false, Green: true */ \ No newline at end of file From abee8262a7d1f5ca40225fa2b82fd3eb7eb99bd6 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Tue, 13 Mar 2012 16:27:15 +0400 Subject: [PATCH 42/43] JetPsiReference.isReferenceTo() also checks for compiled kotlin elements. --- .../org/jetbrains/jet/plugin/references/JetPsiReference.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java index 0e3b3499088..4796049455b 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java @@ -81,7 +81,8 @@ public abstract class JetPsiReference implements PsiPolyVariantReference { @Override public boolean isReferenceTo(PsiElement element) { - return resolve() == element; + PsiElement target = resolve(); + return target == element || target != null && target.getNavigationElement() == element; } @NotNull From 6a8dfc555e5d4f4e09313d4f182d520ed7278de1 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Tue, 13 Mar 2012 16:37:27 +0400 Subject: [PATCH 43/43] Made JetContentBasedFileSubstitutor.getDecompiledPsiFile @Nullable. --- .../jet/plugin/libraries/JetContentBasedFileSubstitutor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java index a6c6cff9829..1cb70a7e021 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java @@ -24,6 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.compiled.ClsFileImpl; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.plugin.JetHighlighter; /** @@ -59,7 +60,7 @@ public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProc return new JetHighlighter(); } - @NotNull + @Nullable @Override public PsiFile getDecompiledPsiFile(PsiFile psiFile) { return JetDecompiledData.getDecompiledData((ClsFileImpl) psiFile).getJetFile();