diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java index 8d95ee78041..d1a16628f24 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java @@ -1029,4 +1029,16 @@ public class JetPsiUtil { return header != null ? header.getQualifiedName() : null; } + + public static JetElement getLocalizingCodeBlock(@NotNull JetNamedDeclaration declaration) { + //noinspection unchecked + JetDeclaration container = + PsiTreeUtil.getParentOfType(declaration, JetNamedFunction.class, JetPropertyAccessor.class, JetClassInitializer.class); + + if (container == null) return null; + + return (container instanceof JetClassInitializer) + ? ((JetClassInitializer) container).getBody() + : ((JetDeclarationWithBody) container).getBodyExpression(); + } } diff --git a/idea/src/org/jetbrains/jet/plugin/hierarchy/HierarchyUtils.java b/idea/src/org/jetbrains/jet/plugin/hierarchy/HierarchyUtils.java index 159590a9e91..3c492ec7df8 100644 --- a/idea/src/org/jetbrains/jet/plugin/hierarchy/HierarchyUtils.java +++ b/idea/src/org/jetbrains/jet/plugin/hierarchy/HierarchyUtils.java @@ -15,9 +15,9 @@ public class HierarchyUtils { return input instanceof PsiMethod || input instanceof PsiClass || input instanceof JetFile || - (input instanceof JetNamedFunction && !((JetNamedFunction) input).isLocal()) || + input instanceof JetNamedFunction || input instanceof JetClassOrObject || - (input instanceof JetProperty && !((JetProperty) input).isLocal()); + input instanceof JetProperty; } }; diff --git a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/CalleeReferenceVisitorBase.java b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/CalleeReferenceVisitorBase.java new file mode 100644 index 00000000000..0574ef7bd73 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/CalleeReferenceVisitorBase.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.hierarchy.calls; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +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.BindingContextUtils; + +public abstract class CalleeReferenceVisitorBase extends JetTreeVisitorVoid { + private final BindingContext bindingContext; + private final boolean deepTraversal; + + protected CalleeReferenceVisitorBase(BindingContext bindingContext, boolean deepTraversal) { + this.bindingContext = bindingContext; + this.deepTraversal = deepTraversal; + } + + protected abstract void processDeclaration(JetReferenceExpression reference, PsiElement declaration); + + @Override + public void visitJetElement(JetElement element) { + if (deepTraversal || !(element instanceof JetClassOrObject || element instanceof JetNamedFunction)) { + super.visitJetElement(element); + } + } + + @Override + public void visitSimpleNameExpression(JetSimpleNameExpression expression) { + DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression); + if (descriptor == null) return; + + PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); + if (declaration == null) return; + + if (isProperty(descriptor, declaration) || isCallable(descriptor, declaration, expression)) { + processDeclaration(expression, declaration); + } + } + + // Accept callees of JetCallElement which refer to Kotlin function, Kotlin class or Java method + private static boolean isCallable(DeclarationDescriptor descriptor, PsiElement declaration, JetSimpleNameExpression reference) { + JetCallElement callElement = PsiTreeUtil.getParentOfType(reference, JetCallElement.class); + if (callElement == null || !PsiTreeUtil.isAncestor(callElement.getCalleeExpression(), reference, false)) return false; + + return descriptor instanceof FunctionDescriptor + && (declaration instanceof JetClassOrObject + || declaration instanceof JetNamedFunction + || declaration instanceof PsiMethod); + } + + // Accept only properties (not local variables or references to Java fields) + private static boolean isProperty(DeclarationDescriptor descriptor, PsiElement declaration) { + return descriptor instanceof PropertyDescriptor && declaration instanceof JetProperty; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.java b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.java index 842cd12dc34..ef6ec887c02 100644 --- a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.java +++ b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.java @@ -12,8 +12,10 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.Navigatable; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; +import com.intellij.psi.*; +import com.intellij.psi.presentation.java.ClassPresentationUtil; +import com.intellij.psi.util.PsiFormatUtil; +import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.ui.LayeredIcon; import com.intellij.util.Function; diff --git a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallTreeStructure.java b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallTreeStructure.java index 3f1d79fc0dc..aad264413e5 100644 --- a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallTreeStructure.java +++ b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallTreeStructure.java @@ -8,14 +8,48 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.asJava.LightClassUtil; import org.jetbrains.jet.lang.psi.*; +import java.util.List; +import java.util.Map; + public abstract class KotlinCallTreeStructure extends HierarchyTreeStructure { - public KotlinCallTreeStructure(@NotNull Project project, HierarchyNodeDescriptor baseDescriptor) { - super(project, baseDescriptor); + protected final String scopeType; + protected final JetElement localizingCodeBlock; + protected final PsiMethod basePsiMethod; + protected final PsiClass basePsiClass; + + public KotlinCallTreeStructure(@NotNull Project project, PsiElement element, String scopeType) { + super(project, createNodeDescriptor(project, element, null)); + + this.scopeType = scopeType; + + localizingCodeBlock = element instanceof JetNamedDeclaration + ? JetPsiUtil.getLocalizingCodeBlock((JetNamedDeclaration) element) + : null; + + if (localizingCodeBlock == null) { + basePsiMethod = getPsiMethod(element); + assert basePsiMethod != null; + + basePsiClass = basePsiMethod.getContainingClass(); + assert basePsiClass != null; + } + else { + basePsiMethod = null; + basePsiClass = null; + } + } + + protected static HierarchyNodeDescriptor createNodeDescriptor(Project project, PsiElement element, HierarchyNodeDescriptor parent) { + boolean root = (parent == null); + return element instanceof JetElement + ? new KotlinCallHierarchyNodeDescriptor(project, parent, element, root, false) + : new CallHierarchyNodeDescriptor(project, parent, element, root, false); } protected static PsiElement getTargetElement(HierarchyNodeDescriptor descriptor) { @@ -24,17 +58,6 @@ public abstract class KotlinCallTreeStructure extends HierarchyTreeStructure { : ((KotlinCallHierarchyNodeDescriptor)descriptor).getTargetElement(); } - @Nullable - protected PsiMethod getBasePsiMethod() { - return getPsiMethod(((KotlinCallHierarchyNodeDescriptor) getBaseDescriptor()).getTargetElement()); - } - - @Nullable - protected PsiClass getBasePsiClass() { - PsiMethod method = getBasePsiMethod(); - return method != null ? method.getContainingClass() : null; - } - private static PsiMethod getClosestContainingClassConstructor(PsiElement element) { while (element != null) { JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(element, JetClassOrObject.class, false); @@ -53,7 +76,9 @@ public abstract class KotlinCallTreeStructure extends HierarchyTreeStructure { } @Nullable - protected static PsiMethod getPsiMethod(PsiElement element) { + protected final PsiMethod getPsiMethod(PsiElement element) { + assert localizingCodeBlock == null : "Can't build light method for local declaration"; + if (element instanceof PsiMethod) { return (PsiMethod) element; } @@ -77,12 +102,6 @@ public abstract class KotlinCallTreeStructure extends HierarchyTreeStructure { return method != null ? method : getClosestContainingClassConstructor(element); } - @Nullable - protected static PsiClass getPsiClass(PsiElement element) { - PsiMethod method = getPsiMethod(element); - return method != null ? method.getContainingClass() : null; - } - protected static CallHierarchyNodeDescriptor getJavaNodeDescriptor(HierarchyNodeDescriptor originalDescriptor) { if (originalDescriptor instanceof CallHierarchyNodeDescriptor) return (CallHierarchyNodeDescriptor) originalDescriptor; @@ -90,6 +109,36 @@ public abstract class KotlinCallTreeStructure extends HierarchyTreeStructure { return ((KotlinCallHierarchyNodeDescriptor) originalDescriptor).getJavaDelegate(); } + protected final Object[] collectNodeDescriptors(HierarchyNodeDescriptor descriptor, List calleeElements) { + HashMap declarationToDescriptorMap = new HashMap(); + for (PsiElement callee : calleeElements) { + if (basePsiClass != null && !isInScope(basePsiClass, callee, scopeType)) continue; + + addNodeDescriptorForElement(callee, declarationToDescriptorMap, descriptor); + } + return declarationToDescriptorMap.values().toArray(new Object[declarationToDescriptorMap.size()]); + } + + protected final void addNodeDescriptorForElement( + PsiElement element, + Map declarationToDescriptorMap, + HierarchyNodeDescriptor descriptor + ) { + HierarchyNodeDescriptor d = declarationToDescriptorMap.get(element); + if (d == null) { + d = createNodeDescriptor(myProject, element, descriptor); + declarationToDescriptorMap.put(element, d); + } + else { + if (d instanceof CallHierarchyNodeDescriptor) { + ((CallHierarchyNodeDescriptor) d).incrementUsageCount(); + } + else if (d instanceof KotlinCallHierarchyNodeDescriptor) { + ((KotlinCallHierarchyNodeDescriptor) d).incrementUsageCount(); + } + } + } + @Override public boolean isAlwaysShowPlus() { return true; diff --git a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCalleeMethodsTreeStructure.java b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCalleeMethodsTreeStructure.java index 4490126b4b9..f5d8051f9aa 100644 --- a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCalleeMethodsTreeStructure.java +++ b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCalleeMethodsTreeStructure.java @@ -24,13 +24,9 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.util.ArrayUtil; -import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -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.BindingContextUtils; import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetClsMethod; import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; @@ -38,87 +34,21 @@ import java.util.ArrayList; import java.util.List; public class KotlinCalleeMethodsTreeStructure extends KotlinCallTreeStructure { - private final String scopeType; - private final CalleeMethodsTreeStructure javaTreeStucture; + private final CalleeMethodsTreeStructure javaTreeStructure; public KotlinCalleeMethodsTreeStructure(@NotNull Project project, @NotNull PsiElement element, String scopeType) { - super(project, new KotlinCallHierarchyNodeDescriptor(project, null, element, true, false)); - this.scopeType = scopeType; - - PsiMethod psiMethod = getPsiMethod(element); - assert psiMethod != null; - - this.javaTreeStucture = new CalleeMethodsTreeStructure(project, psiMethod, scopeType); - } - - private static class VisitorBase extends JetTreeVisitorVoid { - final BindingContext bindingContext; - final ArrayList result; - - private VisitorBase(BindingContext bindingContext, ArrayList result) { - this.bindingContext = bindingContext; - this.result = result; - } - - @Override - public void visitJetElement(JetElement element) { - if (!(element instanceof JetClassOrObject || element instanceof JetNamedFunction)) { - super.visitJetElement(element); - } - } - - @Override - public void visitCallExpression(JetCallExpression expression) { - super.visitCallExpression(expression); - processCallElement(expression); - } - - @Override - public void visitSimpleNameExpression(JetSimpleNameExpression expression) { - DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression); - if (descriptor instanceof PropertyDescriptor) { - PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); - if (declaration instanceof JetProperty) { - result.add(declaration); - } - } - } - - @Override - public void visitDelegationSpecifier(JetDelegationSpecifier specifier) { - if (specifier instanceof JetCallElement) { - processCallElement((JetCallElement) specifier); - } - } - - private void processCallElement(JetCallElement element) { - JetExpression callee = element.getCalleeExpression(); - - JetReferenceExpression referenceExpression = null; - if (callee instanceof JetReferenceExpression) { - referenceExpression = (JetReferenceExpression) callee; - } - else if (callee instanceof JetConstructorCalleeExpression) { - referenceExpression = ((JetConstructorCalleeExpression) callee).getConstructorReferenceExpression(); - } - - if (referenceExpression != null) { - DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, referenceExpression); - if (descriptor == null) return; - - PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); - if (declaration instanceof JetClassOrObject - || (declaration instanceof JetNamedFunction && !((JetNamedFunction) declaration).isLocal()) - || declaration instanceof PsiMethod ) { - result.add(declaration); - } - } - } + super(project, element, scopeType); + this.javaTreeStructure = basePsiMethod != null ? new CalleeMethodsTreeStructure(project, basePsiMethod, scopeType) : null; } private static List getCalleeElements(@NotNull JetElement rootElement, BindingContext bindingContext) { - ArrayList result = new ArrayList(); - JetVisitorVoid visitor = new VisitorBase(bindingContext, result); + final ArrayList result = new ArrayList(); + JetVisitorVoid visitor = new CalleeReferenceVisitorBase(bindingContext, false) { + @Override + protected void processDeclaration(JetReferenceExpression reference, PsiElement declaration) { + result.add(declaration); + } + }; if (rootElement instanceof JetNamedFunction) { JetExpression body = ((JetNamedFunction) rootElement).getBodyExpression(); @@ -157,33 +87,6 @@ public class KotlinCalleeMethodsTreeStructure extends KotlinCallTreeStructure { return result; } - // copied from Java - private Object[] collectNodeDescriptors( - HierarchyNodeDescriptor descriptor, - List calleeElements, - PsiElement baseElement - ) { - HashMap declarationToDescriptorMap = - new HashMap(); - - ArrayList result = new ArrayList(); - - for (PsiElement callee : calleeElements) { - if (!isInScope(baseElement, callee, scopeType)) continue; - - KotlinCallHierarchyNodeDescriptor d = declarationToDescriptorMap.get(callee); - if (d == null) { - d = new KotlinCallHierarchyNodeDescriptor(myProject, descriptor, callee, false, false); - declarationToDescriptorMap.put(callee, d); - result.add(d); - } - else { - d.incrementUsageCount(); - } - } - return ArrayUtil.toObjectArray(result); - } - @Override protected Object[] buildChildren(HierarchyNodeDescriptor descriptor) { PsiElement targetElement = getTargetElement(descriptor); @@ -209,24 +112,20 @@ public class KotlinCalleeMethodsTreeStructure extends KotlinCallTreeStructure { return buildChildrenByKotlinTarget(descriptor, (JetElement) targetElement); } - if (javaTreeStucture != null) { + if (javaTreeStructure != null) { CallHierarchyNodeDescriptor javaDescriptor = descriptor instanceof CallHierarchyNodeDescriptor ? (CallHierarchyNodeDescriptor) descriptor : ((KotlinCallHierarchyNodeDescriptor)descriptor).getJavaDelegate(); - return javaTreeStucture.getChildElements(javaDescriptor); + return javaTreeStructure.getChildElements(javaDescriptor); } return ArrayUtil.EMPTY_OBJECT_ARRAY; } private Object[] buildChildrenByKotlinTarget(HierarchyNodeDescriptor descriptor, JetElement targetElement) { - PsiClass baseClass = getBasePsiClass(); - if (baseClass == null) return ArrayUtil.EMPTY_OBJECT_ARRAY; - BindingContext bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) targetElement.getContainingFile()).getBindingContext(); List calleeDescriptors = getCalleeElements((JetElement) targetElement, bindingContext); - - return collectNodeDescriptors(descriptor, calleeDescriptors, baseClass); + return collectNodeDescriptors(descriptor, calleeDescriptors); } } diff --git a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallerMethodsTreeStructure.java b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallerMethodsTreeStructure.java index c94f81e9baa..b370ce2ab87 100644 --- a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallerMethodsTreeStructure.java +++ b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallerMethodsTreeStructure.java @@ -34,38 +34,61 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.asJava.LightClassUtil; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.plugin.findUsages.FindUsagesUtils; import org.jetbrains.jet.plugin.hierarchy.HierarchyUtils; +import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; import org.jetbrains.jet.plugin.references.JetPsiReference; +import java.util.ArrayList; import java.util.Map; public class KotlinCallerMethodsTreeStructure extends KotlinCallTreeStructure { - private final String scopeType; private final CallerMethodsTreeStructure javaTreeStructure; public KotlinCallerMethodsTreeStructure(@NotNull Project project, @NotNull PsiElement element, String scopeType) { - super(project, new KotlinCallHierarchyNodeDescriptor(project, null, element, true, false)); - this.scopeType = scopeType; - - PsiMethod psiMethod = getPsiMethod(element); - assert psiMethod != null; - - this.javaTreeStructure = new CallerMethodsTreeStructure(project, psiMethod, scopeType); + super(project, element, scopeType); + this.javaTreeStructure = basePsiMethod != null ? new CallerMethodsTreeStructure(project, basePsiMethod, scopeType) : null; } @Override protected Object[] buildChildren(HierarchyNodeDescriptor descriptor) { PsiElement targetElement = getTargetElement(descriptor); - PsiClass baseClass = getBasePsiClass(); - if (baseClass == null) return ArrayUtil.EMPTY_OBJECT_ARRAY; + if (localizingCodeBlock != null) { + return buildLocalizedChildren(targetElement, (KotlinCallHierarchyNodeDescriptor) descriptor); + } - return processCallers(targetElement, descriptor, baseClass); + return processCallers(targetElement, descriptor); } - private Object[] processCallers(PsiElement element, HierarchyNodeDescriptor descriptor, PsiClass baseClass) { - SearchScope searchScope = getSearchScope(scopeType, baseClass); + private Object[] buildLocalizedChildren(final PsiElement element, KotlinCallHierarchyNodeDescriptor descriptor) { + BindingContext bindingContext = + AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) element.getContainingFile()).getBindingContext(); + + final ArrayList result = new ArrayList(); + localizingCodeBlock.accept(new CalleeReferenceVisitorBase(bindingContext, true) { + @Override + protected void processDeclaration(JetReferenceExpression reference, PsiElement declaration) { + if (!declaration.equals(element)) return; + + //noinspection unchecked + PsiElement container = + PsiTreeUtil.getParentOfType(reference, JetNamedFunction.class, JetPropertyAccessor.class, JetClassOrObject.class); + if (container instanceof JetPropertyAccessor) { + container = PsiTreeUtil.getParentOfType(container, JetProperty.class); + } + + if (container != null) { + result.add(container); + } + } + }); + return collectNodeDescriptors(descriptor, result); + } + + private Object[] processCallers(PsiElement element, HierarchyNodeDescriptor descriptor) { + SearchScope searchScope = getSearchScope(scopeType, basePsiClass); Map methodToDescriptorMap = new HashMap(); diff --git a/idea/testData/hierarchy/calls/callees/kotlinAnonymousObject/KotlinAnonymousObject_verification.xml b/idea/testData/hierarchy/calls/callees/kotlinAnonymousObject/KotlinAnonymousObject_verification.xml new file mode 100644 index 00000000000..841f9011f96 --- /dev/null +++ b/idea/testData/hierarchy/calls/callees/kotlinAnonymousObject/KotlinAnonymousObject_verification.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/idea/testData/hierarchy/calls/callees/kotlinAnonymousObject/main0.kt b/idea/testData/hierarchy/calls/callees/kotlinAnonymousObject/main0.kt new file mode 100644 index 00000000000..c340744f3e2 --- /dev/null +++ b/idea/testData/hierarchy/calls/callees/kotlinAnonymousObject/main0.kt @@ -0,0 +1,32 @@ +class KA { + val name = "A" + fun foo(s: String): String = "A: $s" +} + +fun packageFun(s: String): String = s + +val packageVal = "" + +fun client() { + val obj = object { + val bar = run { + val localVal = packageFun("") + + KA().foo(KA().name) + JA().foo(JA().name) + packageFun(localVal) + } + + fun bar() { + KA().foo(KA().name) + JA().foo(JA().name) + } + } + + fun localFun(s: String): String = packageFun(s) + + + KA().foo(KA().name) + JA().foo(JA().name) + localFun(packageVal) +} \ No newline at end of file diff --git a/idea/testData/hierarchy/calls/callees/kotlinAnonymousObject/main1.java b/idea/testData/hierarchy/calls/callees/kotlinAnonymousObject/main1.java new file mode 100644 index 00000000000..f4c2be9cbd9 --- /dev/null +++ b/idea/testData/hierarchy/calls/callees/kotlinAnonymousObject/main1.java @@ -0,0 +1,12 @@ +class JA { + public String name = "A"; + + public JA() { + + } + + public String foo(String s) { + System.out.println(s); + return "A " + s; + } +} diff --git a/idea/testData/hierarchy/calls/callees/kotlinClass/KotlinClass_verification.xml b/idea/testData/hierarchy/calls/callees/kotlinClass/KotlinClass_verification.xml index efb4bd5de75..3f1353add64 100644 --- a/idea/testData/hierarchy/calls/callees/kotlinClass/KotlinClass_verification.xml +++ b/idea/testData/hierarchy/calls/callees/kotlinClass/KotlinClass_verification.xml @@ -1,12 +1,15 @@ - + + + + diff --git a/idea/testData/hierarchy/calls/callees/kotlinFunction/KotlinFunction_verification.xml b/idea/testData/hierarchy/calls/callees/kotlinFunction/KotlinFunction_verification.xml index 9fa3d970e47..05a6d2bdfda 100644 --- a/idea/testData/hierarchy/calls/callees/kotlinFunction/KotlinFunction_verification.xml +++ b/idea/testData/hierarchy/calls/callees/kotlinFunction/KotlinFunction_verification.xml @@ -1,7 +1,10 @@ + + + - + diff --git a/idea/testData/hierarchy/calls/callees/kotlinLocalClass/KotlinLocalClass_verification.xml b/idea/testData/hierarchy/calls/callees/kotlinLocalClass/KotlinLocalClass_verification.xml new file mode 100644 index 00000000000..be5c5a6740b --- /dev/null +++ b/idea/testData/hierarchy/calls/callees/kotlinLocalClass/KotlinLocalClass_verification.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/idea/testData/hierarchy/calls/callees/kotlinLocalClass/main0.kt b/idea/testData/hierarchy/calls/callees/kotlinLocalClass/main0.kt new file mode 100644 index 00000000000..872c4daf587 --- /dev/null +++ b/idea/testData/hierarchy/calls/callees/kotlinLocalClass/main0.kt @@ -0,0 +1,32 @@ +class KA { + val name = "A" + fun foo(s: String): String = "A: $s" +} + +fun packageFun(s: String): String = s + +val packageVal = "" + +fun client() { + class T { + val bar = run { + val localVal = packageFun("") + + KA().foo(KA().name) + JA().foo(JA().name) + packageFun(localVal) + } + + fun bar() { + KA().foo(KA().name) + JA().foo(JA().name) + } + } + + fun localFun(s: String): String = packageFun(s) + + + KA().foo(KA().name) + JA().foo(JA().name) + localFun(packageVal) +} \ No newline at end of file diff --git a/idea/testData/hierarchy/calls/callees/kotlinLocalClass/main1.java b/idea/testData/hierarchy/calls/callees/kotlinLocalClass/main1.java new file mode 100644 index 00000000000..f4c2be9cbd9 --- /dev/null +++ b/idea/testData/hierarchy/calls/callees/kotlinLocalClass/main1.java @@ -0,0 +1,12 @@ +class JA { + public String name = "A"; + + public JA() { + + } + + public String foo(String s) { + System.out.println(s); + return "A " + s; + } +} diff --git a/idea/testData/hierarchy/calls/callees/kotlinLocalFunction/KotlinLocalFunction_verification.xml b/idea/testData/hierarchy/calls/callees/kotlinLocalFunction/KotlinLocalFunction_verification.xml new file mode 100644 index 00000000000..7b3c459a72e --- /dev/null +++ b/idea/testData/hierarchy/calls/callees/kotlinLocalFunction/KotlinLocalFunction_verification.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/idea/testData/hierarchy/calls/callees/kotlinLocalFunction/main0.kt b/idea/testData/hierarchy/calls/callees/kotlinLocalFunction/main0.kt new file mode 100644 index 00000000000..25f80084837 --- /dev/null +++ b/idea/testData/hierarchy/calls/callees/kotlinLocalFunction/main0.kt @@ -0,0 +1,31 @@ +class KA { + val name = "A" + fun foo(s: String): String = "A: $s" +} + +fun packageFun(s: String): String = s + +val packageVal = "" + +fun client() { + fun localFun(s: String): String { + val bar = run { + val localVal = packageFun("") + + KA().foo(KA().name) + JA().foo(JA().name) + packageFun(localVal) + } + + fun bar() { + KA().foo(KA().name) + JA().foo(JA().name) + } + + bar() + } + + KA().foo(KA().name) + JA().foo(JA().name) + localFun(packageVal) +} \ No newline at end of file diff --git a/idea/testData/hierarchy/calls/callees/kotlinLocalFunction/main1.java b/idea/testData/hierarchy/calls/callees/kotlinLocalFunction/main1.java new file mode 100644 index 00000000000..f4c2be9cbd9 --- /dev/null +++ b/idea/testData/hierarchy/calls/callees/kotlinLocalFunction/main1.java @@ -0,0 +1,12 @@ +class JA { + public String name = "A"; + + public JA() { + + } + + public String foo(String s) { + System.out.println(s); + return "A " + s; + } +} diff --git a/idea/testData/hierarchy/calls/callees/kotlinObject/KotlinObject_verification.xml b/idea/testData/hierarchy/calls/callees/kotlinObject/KotlinObject_verification.xml index efb4bd5de75..3f1353add64 100644 --- a/idea/testData/hierarchy/calls/callees/kotlinObject/KotlinObject_verification.xml +++ b/idea/testData/hierarchy/calls/callees/kotlinObject/KotlinObject_verification.xml @@ -1,12 +1,15 @@ - + + + + diff --git a/idea/testData/hierarchy/calls/callees/kotlinProperty/KotlinProperty_verification.xml b/idea/testData/hierarchy/calls/callees/kotlinProperty/KotlinProperty_verification.xml index fc2a03a5df2..3ca42833182 100644 --- a/idea/testData/hierarchy/calls/callees/kotlinProperty/KotlinProperty_verification.xml +++ b/idea/testData/hierarchy/calls/callees/kotlinProperty/KotlinProperty_verification.xml @@ -1,7 +1,10 @@ + + + - + diff --git a/idea/testData/hierarchy/calls/callers/kotlinClass/KotlinClass_verification.xml b/idea/testData/hierarchy/calls/callers/kotlinClass/KotlinClass_verification.xml index 56904b54ddc..25a116a8b14 100644 --- a/idea/testData/hierarchy/calls/callers/kotlinClass/KotlinClass_verification.xml +++ b/idea/testData/hierarchy/calls/callers/kotlinClass/KotlinClass_verification.xml @@ -1,11 +1,12 @@ - - - - - - - + + + + + + + + diff --git a/idea/testData/hierarchy/calls/callers/kotlinFunction/KotlinFunction_verification.xml b/idea/testData/hierarchy/calls/callers/kotlinFunction/KotlinFunction_verification.xml index 43a32cc0524..bb728347b60 100644 --- a/idea/testData/hierarchy/calls/callers/kotlinFunction/KotlinFunction_verification.xml +++ b/idea/testData/hierarchy/calls/callers/kotlinFunction/KotlinFunction_verification.xml @@ -1,11 +1,12 @@ - - - - - - - + + + + + + + + diff --git a/idea/testData/hierarchy/calls/callers/kotlinLocalClass/KotlinLocalClass_verification.xml b/idea/testData/hierarchy/calls/callers/kotlinLocalClass/KotlinLocalClass_verification.xml new file mode 100644 index 00000000000..514eb1c87de --- /dev/null +++ b/idea/testData/hierarchy/calls/callers/kotlinLocalClass/KotlinLocalClass_verification.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/idea/testData/hierarchy/calls/callers/kotlinLocalClass/main0.kt b/idea/testData/hierarchy/calls/callers/kotlinLocalClass/main0.kt new file mode 100644 index 00000000000..14774b0caf9 --- /dev/null +++ b/idea/testData/hierarchy/calls/callers/kotlinLocalClass/main0.kt @@ -0,0 +1,20 @@ +class KClient { + fun client() { + class KA { + val name = "A" + fun foo(s: String): String = "A: $s" + } + + val bar: String = KA().name + + fun bar() { + fun localFun() = KA() + + KA() + } + + object KClientObj { + val a = KA() + } + } +} \ No newline at end of file diff --git a/idea/testData/hierarchy/calls/callers/kotlinLocalFunction/KotlinLocalFunction_verification.xml b/idea/testData/hierarchy/calls/callers/kotlinLocalFunction/KotlinLocalFunction_verification.xml new file mode 100644 index 00000000000..affb0ea8dad --- /dev/null +++ b/idea/testData/hierarchy/calls/callers/kotlinLocalFunction/KotlinLocalFunction_verification.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/idea/testData/hierarchy/calls/callers/kotlinLocalFunction/main0.kt b/idea/testData/hierarchy/calls/callers/kotlinLocalFunction/main0.kt new file mode 100644 index 00000000000..1d9e030d61f --- /dev/null +++ b/idea/testData/hierarchy/calls/callers/kotlinLocalFunction/main0.kt @@ -0,0 +1,17 @@ +class KClient { + fun client() { + fun foo(s: String): String = "" + + val bar: String = foo("") + + fun bar() { + fun localFun() = foo("") + + foo("") + } + + object KClientObj { + val a = foo("") + } + } +} \ No newline at end of file diff --git a/idea/testData/hierarchy/calls/callers/kotlinProperty/KotlinProperty_verification.xml b/idea/testData/hierarchy/calls/callers/kotlinProperty/KotlinProperty_verification.xml index e1d9ffe2b9e..ee96c82c7b4 100644 --- a/idea/testData/hierarchy/calls/callers/kotlinProperty/KotlinProperty_verification.xml +++ b/idea/testData/hierarchy/calls/callers/kotlinProperty/KotlinProperty_verification.xml @@ -1,11 +1,12 @@ - - - - - + + + + + + + - diff --git a/idea/tests/org/jetbrains/jet/plugin/hierarchy/HierarchyTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/hierarchy/HierarchyTestGenerated.java index 2dea2a4f117..b2366afea66 100644 --- a/idea/tests/org/jetbrains/jet/plugin/hierarchy/HierarchyTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/hierarchy/HierarchyTestGenerated.java @@ -217,6 +217,16 @@ public class HierarchyTestGenerated extends AbstractHierarchyTest { doCallerHierarchyTest("idea/testData/hierarchy/calls/callers/kotlinFunction"); } + @TestMetadata("kotlinLocalClass") + public void testKotlinLocalClass() throws Exception { + doCallerHierarchyTest("idea/testData/hierarchy/calls/callers/kotlinLocalClass"); + } + + @TestMetadata("kotlinLocalFunction") + public void testKotlinLocalFunction() throws Exception { + doCallerHierarchyTest("idea/testData/hierarchy/calls/callers/kotlinLocalFunction"); + } + @TestMetadata("kotlinNestedClass") public void testKotlinNestedClass() throws Exception { doCallerHierarchyTest("idea/testData/hierarchy/calls/callers/kotlinNestedClass"); @@ -250,6 +260,11 @@ public class HierarchyTestGenerated extends AbstractHierarchyTest { doCalleeHierarchyTest("idea/testData/hierarchy/calls/callees/javaMethod"); } + @TestMetadata("kotlinAnonymousObject") + public void testKotlinAnonymousObject() throws Exception { + doCalleeHierarchyTest("idea/testData/hierarchy/calls/callees/kotlinAnonymousObject"); + } + @TestMetadata("kotlinClass") public void testKotlinClass() throws Exception { doCalleeHierarchyTest("idea/testData/hierarchy/calls/callees/kotlinClass"); @@ -270,6 +285,16 @@ public class HierarchyTestGenerated extends AbstractHierarchyTest { doCalleeHierarchyTest("idea/testData/hierarchy/calls/callees/kotlinFunction"); } + @TestMetadata("kotlinLocalClass") + public void testKotlinLocalClass() throws Exception { + doCalleeHierarchyTest("idea/testData/hierarchy/calls/callees/kotlinLocalClass"); + } + + @TestMetadata("kotlinLocalFunction") + public void testKotlinLocalFunction() throws Exception { + doCalleeHierarchyTest("idea/testData/hierarchy/calls/callees/kotlinLocalFunction"); + } + @TestMetadata("kotlinNestedClass") public void testKotlinNestedClass() throws Exception { doCalleeHierarchyTest("idea/testData/hierarchy/calls/callees/kotlinNestedClass");