diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java index 69d473ac88b..228643eefd2 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java @@ -17,7 +17,8 @@ package org.jetbrains.jet.plugin.libraries; import com.google.common.base.Predicate; -import com.google.common.collect.*; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.roots.OrderRootType; @@ -30,30 +31,29 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.GlobalSearchScopes; import com.intellij.psi.stubs.StringStubIndexExtension; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import org.jetbrains.jet.lang.DefaultModuleConfiguration; -import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.lazy.FileBasedDeclarationProviderFactory; import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; -import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex; -import org.jetbrains.jet.renderer.DescriptorRenderer; -import org.jetbrains.jet.util.CommonSuppliers; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; +import static org.jetbrains.jet.plugin.libraries.MemberMatching.*; + public class JetSourceNavigationHelper { private static boolean forceResolve = false; @@ -126,46 +126,6 @@ public class JetSourceNavigationHelper { return false; } - private static String getTypeShortName(@NotNull JetTypeReference typeReference) { - JetTypeElement typeElement = typeReference.getTypeElement(); - assert typeElement != null; - return typeElement.accept(new JetVisitor() { - @Override - public String visitDeclaration(JetDeclaration declaration, Void data) { - throw new IllegalStateException("This visitor shouldn't be invoked for " + declaration.getClass()); - } - - @Override - public String visitUserType(JetUserType type, Void data) { - JetSimpleNameExpression referenceExpression = type.getReferenceExpression(); - assert referenceExpression != null; - return referenceExpression.getReferencedName(); - } - - @Override - public String visitFunctionType(JetFunctionType type, Void data) { - KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); - int parameterCount = type.getParameters().size(); - - if (type.getReceiverTypeRef() == null) { - return builtIns.getFunction(parameterCount).getName().getName(); - } - else { - return builtIns.getExtensionFunction(parameterCount).getName().getName(); - } - } - - @Override - public String visitNullableType(JetNullableType nullableType, Void data) { - return nullableType.getInnerType().accept(this, null); - } - }, null); - } - - private static boolean typesHaveSameShortName(@NotNull JetTypeReference a, @NotNull JetTypeReference b) { - return getTypeShortName(a).equals(getTypeShortName(b)); - } - @Nullable private static JetNamedDeclaration findSpecialProperty(@NotNull Name memberName, @NotNull JetClass containingClass) { // property constructor parameters @@ -349,145 +309,16 @@ public class JetSourceNavigationHelper { if (decompiledReceiver != null) { JetTypeReference candidateReceiver = navigationStrategy.getReceiverType(candidate); assert candidateReceiver != null; - if (!typesHaveSameShortName(decompiledReceiver, candidateReceiver)) { + if (!MemberMatching.typesHaveSameShortName(decompiledReceiver, candidateReceiver)) { return false; } } - return parameterShortTypesMatch(navigationStrategy, candidate, decompiledDeclaration); + return MemberMatching.parameterShortTypesMatch(navigationStrategy, candidate, decompiledDeclaration); } }); } - private static boolean receiversMatch( - @Nullable JetTypeReference receiverTypeRef, - @Nullable ReceiverParameterDescriptor receiverParameter - ) { - if (receiverTypeRef == null && receiverParameter == null) { - return true; - } - if (receiverTypeRef != null && receiverParameter != null) { - return receiverTypeRef.getText().equals(DescriptorRenderer.TEXT.renderType(receiverParameter.getType())); - } - return false; - } - - private static boolean valueParametersTypesMatch( - @NotNull MemberNavigationStrategy navigationStrategy, - @NotNull Decl declaration, - @NotNull Descr descriptor - ) { - List declarationParameters = navigationStrategy.getValueParameters(declaration); - List descriptorParameters = navigationStrategy.getValueParameters(descriptor); - if (descriptorParameters.size() != declarationParameters.size()) { - return false; - } - - for (int i = 0; i < descriptorParameters.size(); i++) { - ValueParameterDescriptor descriptorParameter = descriptorParameters.get(i); - JetParameter declarationParameter = declarationParameters.get(i); - JetTypeReference typeReference = declarationParameter.getTypeReference(); - if (typeReference == null) { - return false; - } - JetModifierList modifierList = declarationParameter.getModifierList(); - boolean varargInDeclaration = modifierList != null && modifierList.hasModifier(JetTokens.VARARG_KEYWORD); - boolean varargInDescriptor = descriptorParameter.getVarargElementType() != null; - if (varargInDeclaration != varargInDescriptor) { - return false; - } - String declarationTypeText = typeReference.getText(); - - JetType typeToRender = varargInDeclaration ? descriptorParameter.getVarargElementType() : descriptorParameter.getType(); - assert typeToRender != null; - String descriptorParameterText = DescriptorRenderer.TEXT.renderType(typeToRender); - if (!declarationTypeText.equals(descriptorParameterText)) { - return false; - } - } - return true; - } - - private static boolean parameterShortTypesMatch( - @NotNull MemberNavigationStrategy navigationStrategy, - @NotNull Decl a, - @NotNull Decl b - ) { - List aParameters = navigationStrategy.getValueParameters(a); - List bParameters = navigationStrategy.getValueParameters(b); - if (aParameters.size() != bParameters.size()) { - return false; - } - for (int i = 0; i < aParameters.size(); i++) { - JetTypeReference aType = aParameters.get(i).getTypeReference(); - JetTypeReference bType = bParameters.get(i).getTypeReference(); - - assert aType != null; - assert bType != null; - - if (!typesHaveSameShortName(aType, bType)) { - return false; - } - } - return true; - } - - private static boolean typeParametersMatch( - @NotNull JetTypeParameterListOwner typeParameterListOwner, - @NotNull List typeParameterDescriptors - ) { - List decompiledParameters = typeParameterListOwner.getTypeParameters(); - if (decompiledParameters.size() != typeParameterDescriptors.size()) { - return false; - } - - Multimap decompiledParameterToBounds = Multimaps.newSetMultimap( - Maps.>newHashMap(), CommonSuppliers.getHashSetSupplier()); - for (JetTypeParameter parameter : decompiledParameters) { - JetTypeReference extendsBound = parameter.getExtendsBound(); - if (extendsBound != null) { - decompiledParameterToBounds.put(parameter.getNameAsName(), extendsBound.getText()); - } - } - - for (JetTypeConstraint typeConstraint : typeParameterListOwner.getTypeConstraints()) { - JetSimpleNameExpression typeParameterName = typeConstraint.getSubjectTypeParameterName(); - assert typeParameterName != null; - - JetTypeReference bound = typeConstraint.getBoundTypeReference(); - assert bound != null; - - decompiledParameterToBounds.put(typeParameterName.getReferencedNameAsName(), bound.getText()); - } - - for (int i = 0; i < decompiledParameters.size(); i++) { - JetTypeParameter decompiledParameter = decompiledParameters.get(i); - TypeParameterDescriptor descriptor = typeParameterDescriptors.get(i); - - Name name = decompiledParameter.getNameAsName(); - assert name != null; - if (!name.equals(descriptor.getName())) { - return false; - } - - Set descriptorUpperBounds = Sets.newHashSet(ContainerUtil.map( - descriptor.getUpperBounds(), new Function() { - @Override - public String fun(JetType type) { - return DescriptorRenderer.TEXT.renderType(type); - } - })); - - Set decompiledUpperBounds = decompiledParameterToBounds.get(descriptor.getName()).isEmpty() - ? Sets.newHashSet(DescriptorRenderer.TEXT.renderType(KotlinBuiltIns.getInstance().getDefaultBound())) - : Sets.newHashSet(decompiledParameterToBounds.get(descriptor.getName())); - if (!descriptorUpperBounds.equals(decompiledUpperBounds)) { - return false; - } - } - return true; - } - @Nullable public static JetNamedDeclaration getSourceProperty(final @NotNull JetProperty decompiledProperty) { return getSourcePropertyOrFunction(decompiledProperty, new MemberNavigationStrategy.PropertyStrategy()); diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/MemberMatching.java b/idea/src/org/jetbrains/jet/plugin/libraries/MemberMatching.java new file mode 100644 index 00000000000..1a660dee12e --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/libraries/MemberMatching.java @@ -0,0 +1,215 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.libraries; + +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.Sets; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.lexer.JetTokens; +import org.jetbrains.jet.renderer.DescriptorRenderer; +import org.jetbrains.jet.util.CommonSuppliers; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +public class MemberMatching { + private static String getTypeShortName(@NotNull JetTypeReference typeReference) { + JetTypeElement typeElement = typeReference.getTypeElement(); + assert typeElement != null; + return typeElement.accept(new JetVisitor() { + @Override + public String visitDeclaration(JetDeclaration declaration, Void data) { + throw new IllegalStateException("This visitor shouldn't be invoked for " + declaration.getClass()); + } + + @Override + public String visitUserType(JetUserType type, Void data) { + JetSimpleNameExpression referenceExpression = type.getReferenceExpression(); + assert referenceExpression != null; + return referenceExpression.getReferencedName(); + } + + @Override + public String visitFunctionType(JetFunctionType type, Void data) { + KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); + int parameterCount = type.getParameters().size(); + + if (type.getReceiverTypeRef() == null) { + return builtIns.getFunction(parameterCount).getName().getName(); + } + else { + return builtIns.getExtensionFunction(parameterCount).getName().getName(); + } + } + + @Override + public String visitNullableType(JetNullableType nullableType, Void data) { + return nullableType.getInnerType().accept(this, null); + } + }, null); + } + + static boolean typesHaveSameShortName(@NotNull JetTypeReference a, @NotNull JetTypeReference b) { + return getTypeShortName(a).equals(getTypeShortName(b)); + } + + static boolean receiversMatch( + @Nullable JetTypeReference receiverTypeRef, + @Nullable ReceiverParameterDescriptor receiverParameter + ) { + if (receiverTypeRef == null && receiverParameter == null) { + return true; + } + if (receiverTypeRef != null && receiverParameter != null) { + return receiverTypeRef.getText().equals(DescriptorRenderer.TEXT.renderType(receiverParameter.getType())); + } + return false; + } + + static boolean valueParametersTypesMatch( + @NotNull MemberNavigationStrategy navigationStrategy, + @NotNull Decl declaration, + @NotNull Descr descriptor + ) { + List declarationParameters = navigationStrategy.getValueParameters(declaration); + List descriptorParameters = navigationStrategy.getValueParameters(descriptor); + if (descriptorParameters.size() != declarationParameters.size()) { + return false; + } + + for (int i = 0; i < descriptorParameters.size(); i++) { + ValueParameterDescriptor descriptorParameter = descriptorParameters.get(i); + JetParameter declarationParameter = declarationParameters.get(i); + JetTypeReference typeReference = declarationParameter.getTypeReference(); + if (typeReference == null) { + return false; + } + JetModifierList modifierList = declarationParameter.getModifierList(); + boolean varargInDeclaration = modifierList != null && modifierList.hasModifier(JetTokens.VARARG_KEYWORD); + boolean varargInDescriptor = descriptorParameter.getVarargElementType() != null; + if (varargInDeclaration != varargInDescriptor) { + return false; + } + String declarationTypeText = typeReference.getText(); + + JetType typeToRender = varargInDeclaration ? descriptorParameter.getVarargElementType() : descriptorParameter.getType(); + assert typeToRender != null; + String descriptorParameterText = DescriptorRenderer.TEXT.renderType(typeToRender); + if (!declarationTypeText.equals(descriptorParameterText)) { + return false; + } + } + return true; + } + + static boolean parameterShortTypesMatch( + @NotNull MemberNavigationStrategy navigationStrategy, + @NotNull Decl a, + @NotNull Decl b + ) { + List aParameters = navigationStrategy.getValueParameters(a); + List bParameters = navigationStrategy.getValueParameters(b); + if (aParameters.size() != bParameters.size()) { + return false; + } + for (int i = 0; i < aParameters.size(); i++) { + JetTypeReference aType = aParameters.get(i).getTypeReference(); + JetTypeReference bType = bParameters.get(i).getTypeReference(); + + assert aType != null; + assert bType != null; + + if (!typesHaveSameShortName(aType, bType)) { + return false; + } + } + return true; + } + + static boolean typeParametersMatch( + @NotNull JetTypeParameterListOwner typeParameterListOwner, + @NotNull List typeParameterDescriptors + ) { + List decompiledParameters = typeParameterListOwner.getTypeParameters(); + if (decompiledParameters.size() != typeParameterDescriptors.size()) { + return false; + } + + Multimap decompiledParameterToBounds = Multimaps.newSetMultimap( + Maps.>newHashMap(), CommonSuppliers.getHashSetSupplier()); + for (JetTypeParameter parameter : decompiledParameters) { + JetTypeReference extendsBound = parameter.getExtendsBound(); + if (extendsBound != null) { + decompiledParameterToBounds.put(parameter.getNameAsName(), extendsBound.getText()); + } + } + + for (JetTypeConstraint typeConstraint : typeParameterListOwner.getTypeConstraints()) { + JetSimpleNameExpression typeParameterName = typeConstraint.getSubjectTypeParameterName(); + assert typeParameterName != null; + + JetTypeReference bound = typeConstraint.getBoundTypeReference(); + assert bound != null; + + decompiledParameterToBounds.put(typeParameterName.getReferencedNameAsName(), bound.getText()); + } + + for (int i = 0; i < decompiledParameters.size(); i++) { + JetTypeParameter decompiledParameter = decompiledParameters.get(i); + TypeParameterDescriptor descriptor = typeParameterDescriptors.get(i); + + Name name = decompiledParameter.getNameAsName(); + assert name != null; + if (!name.equals(descriptor.getName())) { + return false; + } + + Set descriptorUpperBounds = Sets.newHashSet(ContainerUtil.map( + descriptor.getUpperBounds(), new Function() { + @Override + public String fun(JetType type) { + return DescriptorRenderer.TEXT.renderType(type); + } + })); + + Set decompiledUpperBounds = decompiledParameterToBounds.get(descriptor.getName()).isEmpty() + ? Sets.newHashSet(DescriptorRenderer.TEXT.renderType(KotlinBuiltIns.getInstance().getDefaultBound())) + : Sets.newHashSet(decompiledParameterToBounds.get(descriptor.getName())); + if (!descriptorUpperBounds.equals(decompiledUpperBounds)) { + return false; + } + } + return true; + } + + private MemberMatching() { + } +}