diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 93071deef14..e2aafb25ed7 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -23,6 +23,7 @@ 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.FqName; +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; @@ -144,8 +145,8 @@ public class NamespaceCodegen { } String name = fqName.getFqName().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.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java index 46cb4da7a53..7a57a9db989 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 @@ -87,7 +87,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 e7ff901dec7..14f77fddeb2 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 @@ -1021,7 +1021,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(); @@ -1281,7 +1281,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 b72d55ab414..354b8b5e21a 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; 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 198b4aa3ef9..0ff9bafc89e 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 @@ -99,7 +99,7 @@ public class JavaPackageScope extends JavaClassOrPackageScope { @Override public Collection getAllDescriptors() { if (allDescriptors == null) { - allDescriptors = Sets.newHashSet(); + allDescriptors = Sets.newLinkedHashSet(); if (psiClass != null) { allDescriptors.addAll(semanticServices.getDescriptorResolver().resolveMethods(psiClass, descriptor)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqName.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqName.java index 2537fe3a944..f54bc56e8a3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqName.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqName.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2010-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. diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 260a15d1941..d8b17b08a6f 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; @@ -37,6 +38,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() { @@ -102,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()); @@ -182,10 +192,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 +214,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(); } @@ -277,16 +295,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 @@ -342,8 +359,7 @@ public class DescriptorRenderer implements Renderer { builder.append(", "); } } - builder.append("> "); - return true; + builder.append(">"); } return false; } @@ -365,19 +381,38 @@ 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); } public void renderClassDescriptor(ClassDescriptor descriptor, StringBuilder builder, String keyword) { - renderModality(descriptor.getModality(), builder); - builder.append(renderKeyword(keyword)).append(" "); - renderName(descriptor, builder); - renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder); + if (descriptor.getKind() != ClassKind.TRAIT) { + renderModality(descriptor.getModality(), 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()) { + 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(); 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/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 4d339d8b8c9..00374749a78 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,9 @@ + + + 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..24e0d2d5576 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java @@ -0,0 +1,193 @@ +/* + * 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.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.FqName; +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, 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(new FqName(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/JetClsNavigationPolicy.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java new file mode 100644 index 00000000000..0a824090c0a --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetClsNavigationPolicy.java @@ -0,0 +1,58 @@ +/* + * 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.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; + +/** + * @author Evgeny Gerashchenko + * @since 3/2/12 + */ +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.isKotlinFile(clsElement.getProject(), virtualFile)) { + return null; + } + JetDecompiledData decompiledData = JetDecompiledData.getDecompiledData((ClsFileImpl) clsElement.getContainingFile()); + return decompiledData.getJetDeclarationByClsElement(clsElement); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java new file mode 100644 index 00000000000..1cb70a7e021 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java @@ -0,0 +1,69 @@ +/* + * 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.lang.Language; +import com.intellij.openapi.fileTypes.ContentBasedClassFileProcessor; +import com.intellij.openapi.fileTypes.SyntaxHighlighter; +import com.intellij.openapi.project.Project; +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; + +/** + * @author Evgeny Gerashchenko + * @since 2/15/12 + */ +public class JetContentBasedFileSubstitutor implements ContentBasedClassFileProcessor { + + @Override + public boolean isApplicable(Project project, VirtualFile file) { + return JetDecompiledData.isKotlinFile(project, file); + } + + @NotNull + @Override + public String obtainFileText(Project project, VirtualFile file) { + if (JetDecompiledData.isKotlinFile(project, file)) { + ClsFileImpl clsFile = JetDecompiledData.getClsFile(project, file); + assert clsFile != null; + return JetDecompiledData.getDecompiledData(clsFile).getJetFile().getText(); + } + return ""; + } + + @Override + public Language obtainLanguageForFile(VirtualFile file) { + return null; + } + + @NotNull + @Override + public SyntaxHighlighter createHighlighter(Project project, VirtualFile vFile) { + return new JetHighlighter(); + } + + @Nullable + @Override + public PsiFile getDecompiledPsiFile(PsiFile psiFile) { + return JetDecompiledData.getDecompiledData((ClsFileImpl) psiFile).getJetFile(); + } +} + diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java new file mode 100644 index 00000000000..dc9d539bad5 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDecompiledData.java @@ -0,0 +1,106 @@ +/* + * 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.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.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; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; +import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetFile; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Evgeny Gerashchenko + * @since 3/2/12 + */ +@SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") +public class JetDecompiledData { + private JetFile myJetFile; + + 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"); + + JetDecompiledData(JetFile jetFile, Map clsElementJetDeclarationMap) { + myJetFile = jetFile; + myClsElementsToJetElements = clsElementJetDeclarationMap; + } + + @NotNull + public JetFile getJetFile() { + return myJetFile; + } + + public JetDeclaration getJetDeclarationByClsElement(ClsElementImpl clsElement) { + return myClsElementsToJetElements.get(clsElement); + } + + @Nullable + public static ClsFileImpl getClsFile(@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; + 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); + } + + @NotNull + public static JetDecompiledData getDecompiledData(@NotNull ClsFileImpl clsFile) { + synchronized (LOCK) { + if (clsFile.getUserData(USER_DATA_KEY) == null) { + clsFile.putUserData(USER_DATA_KEY, DecompiledDataFactory.createDecompiledData(clsFile)); + } + JetDecompiledData decompiledData = clsFile.getUserData(USER_DATA_KEY); + assert decompiledData != null; + return decompiledData; + } + } + + @TestOnly + Map getClsElementsToJetElements() { + return myClsElementsToJetElements; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java new file mode 100644 index 00000000000..6348b7be1db --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetDummyClassFileViewProvider.java @@ -0,0 +1,183 @@ +/* + * 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.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 org.jetbrains.jet.plugin.JetLanguage; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * @author Evgeny Gerashchenko + * @since 3/2/12 + */ +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 String 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) { + if (JetLanguage.INSTANCE != target) { + return null; + } + 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) { + if (JetLanguage.class != lang) { + return null; + } + 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) { + if (JetLanguage.INSTANCE != language) { + return null; + } + 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); + } +} 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 diff --git a/idea/testData/libraries/AbstractClass.kt b/idea/testData/libraries/AbstractClass.kt new file mode 100644 index 00000000000..33cbc85ca07 --- /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/ClassWithAbstractAndOpenMembers.kt b/idea/testData/libraries/ClassWithAbstractAndOpenMembers.kt new file mode 100644 index 00000000000..b2c911f2cf0 --- /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..1e5516ba4ea --- /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..60528a70a69 --- /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..d25fc5a61ec --- /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..8c4007af99f --- /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..4d788cd595e --- /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..4529fc325bc --- /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/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/testData/libraries/namespace.kt b/idea/testData/libraries/namespace.kt new file mode 100644 index 00000000000..269bc0edb06 --- /dev/null +++ b/idea/testData/libraries/namespace.kt @@ -0,0 +1,10 @@ +// 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 */ }] + +[val globalVal : #(jet.Int, jet.String)] /* compiled code */ + +[val globalValWithGetter : jet.Long] /* compiled code */ 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 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 a1a19fa074a..21c82df53b1 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; 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..ccbdcce706e --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/libraries/LibrariesTest.java @@ -0,0 +1,171 @@ +/* + * 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.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 + */ +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(); + } + + 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() { + 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(getTestName(false) + ".class"); + assertNotNull(classFile); + return classFile; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + String libraryDir = FileUtil.getTempDirectory(); + int compilerExec = new KotlinCompiler().exec("-src", TEST_DATA_PATH + "/library", "-output", libraryDir); + assertEquals(0, compilerExec); + 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(); + } + }); + } +}