Added no-resolve optimization for class functions and properties.
This commit is contained in:
@@ -50,6 +50,7 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
|||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
import org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex;
|
||||||
import org.jetbrains.jet.plugin.stubindex.JetTopLevelFunctionsFqnNameIndex;
|
import org.jetbrains.jet.plugin.stubindex.JetTopLevelFunctionsFqnNameIndex;
|
||||||
import org.jetbrains.jet.plugin.stubindex.JetTopLevelPropertiesFqnNameIndex;
|
import org.jetbrains.jet.plugin.stubindex.JetTopLevelPropertiesFqnNameIndex;
|
||||||
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||||
@@ -100,15 +101,26 @@ public class JetSourceNavigationHelper {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JetClassOrObject getSourceClassOrObject(@NotNull JetClassOrObject decompiledClassOrObject) {
|
public static JetClassOrObject getSourceClassOrObject(@NotNull JetClassOrObject decompiledClassOrObject) {
|
||||||
Pair<BindingContext, ClassDescriptor> bindingContextAndClassDescriptor = getBindingContextAndClassDescriptor(
|
if (decompiledClassOrObject instanceof JetObjectDeclaration && decompiledClassOrObject.getParent() instanceof JetClassObject) {
|
||||||
decompiledClassOrObject);
|
// class object case
|
||||||
if (bindingContextAndClassDescriptor == null) return null;
|
|
||||||
PsiElement declaration = BindingContextUtils.classDescriptorToDeclaration(
|
JetClass decompiledClass = PsiTreeUtil.getParentOfType(decompiledClassOrObject, JetClass.class);
|
||||||
bindingContextAndClassDescriptor.first, bindingContextAndClassDescriptor.second);
|
assert decompiledClass != null;
|
||||||
if (declaration == null) {
|
|
||||||
throw new IllegalStateException("class not found by " + bindingContextAndClassDescriptor.second);
|
JetClass sourceClass = (JetClass) getSourceForNamedClassOrObject(decompiledClass);
|
||||||
|
if (sourceClass == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceClass.hasModifier(JetTokens.ENUM_KEYWORD)) {
|
||||||
|
return sourceClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
JetClassObject classObject = sourceClass.getClassObject();
|
||||||
|
assert classObject != null;
|
||||||
|
return classObject.getObjectDeclaration();
|
||||||
}
|
}
|
||||||
return (JetClassOrObject) declaration;
|
return getSourceForNamedClassOrObject(decompiledClassOrObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -267,6 +279,27 @@ public class JetSourceNavigationHelper {
|
|||||||
return candidates.isEmpty() ? null : candidates.iterator().next();
|
return candidates.isEmpty() ? null : candidates.iterator().next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static JetNamedDeclaration findSpecialProperty(@NotNull Name memberName, @NotNull JetClass containingClass) {
|
||||||
|
// property constructor parameters
|
||||||
|
List<JetParameter> constructorParameters = containingClass.getPrimaryConstructorParameters();
|
||||||
|
for (JetParameter constructorParameter : constructorParameters) {
|
||||||
|
if (memberName.equals(constructorParameter.getNameAsName()) && constructorParameter.getValOrVarNode() != null) {
|
||||||
|
return constructorParameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// enum entries
|
||||||
|
if (containingClass.hasModifier(JetTokens.ENUM_KEYWORD)) {
|
||||||
|
for (JetEnumEntry enumEntry : ContainerUtil.findAll(containingClass.getDeclarations(), JetEnumEntry.class)) {
|
||||||
|
if (memberName.equals(enumEntry.getNameAsName())) {
|
||||||
|
return enumEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static <Decl extends JetNamedDeclaration, Descr extends CallableDescriptor> JetNamedDeclaration
|
private static <Decl extends JetNamedDeclaration, Descr extends CallableDescriptor> JetNamedDeclaration
|
||||||
getSourcePropertyOrFunction(
|
getSourcePropertyOrFunction(
|
||||||
@@ -277,22 +310,43 @@ public class JetSourceNavigationHelper {
|
|||||||
assert memberNameAsString != null;
|
assert memberNameAsString != null;
|
||||||
Name memberName = Name.identifier(memberNameAsString);
|
Name memberName = Name.identifier(memberNameAsString);
|
||||||
|
|
||||||
if (decompiledDeclaration.getParent() instanceof JetFile) {
|
PsiElement decompiledContainer = decompiledDeclaration.getParent();
|
||||||
Collection<Decl> candidates = getInitialCandidates(decompiledDeclaration, navigationStrategy);
|
|
||||||
|
|
||||||
candidates = filterByReceiverPresenceAndParametersCount(decompiledDeclaration, navigationStrategy, candidates);
|
Collection<Decl> candidates;
|
||||||
|
if (decompiledContainer instanceof JetFile) {
|
||||||
|
candidates = getInitialCandidates(decompiledDeclaration, navigationStrategy);
|
||||||
|
}
|
||||||
|
else if (decompiledContainer instanceof JetClassBody) {
|
||||||
|
JetClassOrObject decompiledClassOrObject = (JetClassOrObject) decompiledContainer.getParent();
|
||||||
|
JetClassOrObject sourceClassOrObject = getSourceClassOrObject(decompiledClassOrObject);
|
||||||
|
|
||||||
|
candidates = sourceClassOrObject == null
|
||||||
|
? Collections.<Decl>emptyList()
|
||||||
|
: getInitialCandidates(sourceClassOrObject, memberName, navigationStrategy.getDeclarationClass());
|
||||||
|
|
||||||
|
if (candidates.isEmpty()) {
|
||||||
|
if (decompiledDeclaration instanceof JetProperty && sourceClassOrObject instanceof JetClass) {
|
||||||
|
return findSpecialProperty(memberName, (JetClass) sourceClassOrObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalStateException("Unexpected container of decompiled declaration: "
|
||||||
|
+ decompiledContainer.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
candidates = filterByReceiverPresenceAndParametersCount(decompiledDeclaration, navigationStrategy, candidates);
|
||||||
|
|
||||||
|
if (candidates.size() <= 1) {
|
||||||
|
return getUnambiguousCandidate(candidates);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!haveRenamesInImports(getContainingFiles(candidates))) {
|
||||||
|
candidates = filterByReceiverAndParameterTypes(decompiledDeclaration, navigationStrategy, candidates);
|
||||||
|
|
||||||
if (candidates.size() <= 1) {
|
if (candidates.size() <= 1) {
|
||||||
return getUnambiguousCandidate(candidates);
|
return getUnambiguousCandidate(candidates);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!haveRenamesInImports(getContainingFiles(candidates))) {
|
|
||||||
candidates = filterByReceiverAndParameterTypes(decompiledDeclaration, navigationStrategy, candidates);
|
|
||||||
|
|
||||||
if (candidates.size() <= 1) {
|
|
||||||
return getUnambiguousCandidate(candidates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<BindingContext, JetScope> contextAndMemberScope = getBindingContextAndMemberScopeForLibrarySources(decompiledDeclaration);
|
Pair<BindingContext, JetScope> contextAndMemberScope = getBindingContextAndMemberScopeForLibrarySources(decompiledDeclaration);
|
||||||
@@ -313,6 +367,23 @@ public class JetSourceNavigationHelper {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static JetClassOrObject getSourceForNamedClassOrObject(@NotNull JetClassOrObject decompiledClassOrObject) {
|
||||||
|
FqName classFqName = JetPsiUtil.getFQName((JetNamedDeclaration) decompiledClassOrObject);
|
||||||
|
assert classFqName != null;
|
||||||
|
|
||||||
|
GlobalSearchScope librarySourcesScope = createLibrarySourcesScope((JetNamedDeclaration) decompiledClassOrObject);
|
||||||
|
if (librarySourcesScope == GlobalSearchScope.EMPTY_SCOPE) { // .getProject() == null for EMPTY_SCOPE, and this breaks code
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Collection<JetClassOrObject> classes = JetFullClassNameIndex.getInstance()
|
||||||
|
.get(classFqName.getFqName(), decompiledClassOrObject.getProject(), librarySourcesScope);
|
||||||
|
if (classes.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return classes.iterator().next(); // if there are more than one class with this FQ, find first of them
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static <Decl extends JetNamedDeclaration, Descr extends CallableDescriptor> Collection<Decl> getInitialCandidates(
|
private static <Decl extends JetNamedDeclaration, Descr extends CallableDescriptor> Collection<Decl> getInitialCandidates(
|
||||||
@NotNull Decl decompiledDeclaration,
|
@NotNull Decl decompiledDeclaration,
|
||||||
@@ -329,6 +400,21 @@ public class JetSourceNavigationHelper {
|
|||||||
return index.get(memberFqName.getFqName(), decompiledDeclaration.getProject(), librarySourcesScope);
|
return index.get(memberFqName.getFqName(), decompiledDeclaration.getProject(), librarySourcesScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static <Decl extends JetNamedDeclaration> List<Decl> getInitialCandidates(
|
||||||
|
@NotNull JetClassOrObject sourceClassOrObject,
|
||||||
|
@NotNull final Name name,
|
||||||
|
@NotNull Class<Decl> declarationClass
|
||||||
|
) {
|
||||||
|
List<Decl> allByClass = ContainerUtil.findAll(sourceClassOrObject.getDeclarations(), declarationClass);
|
||||||
|
return ContainerUtil.filter(allByClass, new Condition<Decl>() {
|
||||||
|
@Override
|
||||||
|
public boolean value(Decl declaration) {
|
||||||
|
return name.equals(declaration.getNameAsSafeName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static <Decl extends JetNamedDeclaration, Descr extends CallableDescriptor> List<Decl> filterByReceiverPresenceAndParametersCount(
|
private static <Decl extends JetNamedDeclaration, Descr extends CallableDescriptor> List<Decl> filterByReceiverPresenceAndParametersCount(
|
||||||
final @NotNull Decl decompiledDeclaration,
|
final @NotNull Decl decompiledDeclaration,
|
||||||
@@ -396,6 +482,9 @@ public class JetSourceNavigationHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private interface NavigationStrategy<Decl extends JetNamedDeclaration, Descr extends CallableDescriptor> {
|
private interface NavigationStrategy<Decl extends JetNamedDeclaration, Descr extends CallableDescriptor> {
|
||||||
|
@NotNull
|
||||||
|
Class<Decl> getDeclarationClass();
|
||||||
|
|
||||||
boolean declarationsMatchByParameterCount(@NotNull Decl a, @NotNull Decl b);
|
boolean declarationsMatchByParameterCount(@NotNull Decl a, @NotNull Decl b);
|
||||||
|
|
||||||
boolean declarationsMatchByParameterTypes(@NotNull Decl a, @NotNull Decl b);
|
boolean declarationsMatchByParameterTypes(@NotNull Decl a, @NotNull Decl b);
|
||||||
@@ -411,6 +500,12 @@ public class JetSourceNavigationHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class FunctionNavigationStrategy implements NavigationStrategy<JetNamedFunction, FunctionDescriptor> {
|
private static class FunctionNavigationStrategy implements NavigationStrategy<JetNamedFunction, FunctionDescriptor> {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Class<JetNamedFunction> getDeclarationClass() {
|
||||||
|
return JetNamedFunction.class;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean declarationsMatchByParameterCount(@NotNull JetNamedFunction a, @NotNull JetNamedFunction b) {
|
public boolean declarationsMatchByParameterCount(@NotNull JetNamedFunction a, @NotNull JetNamedFunction b) {
|
||||||
return a.getValueParameters().size() == b.getValueParameters().size();
|
return a.getValueParameters().size() == b.getValueParameters().size();
|
||||||
@@ -488,6 +583,12 @@ public class JetSourceNavigationHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class PropertyNavigationStrategy implements NavigationStrategy<JetProperty, VariableDescriptor> {
|
private static class PropertyNavigationStrategy implements NavigationStrategy<JetProperty, VariableDescriptor> {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Class<JetProperty> getDeclarationClass() {
|
||||||
|
return JetProperty.class;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean declarationsMatchByParameterCount(@NotNull JetProperty a, @NotNull JetProperty b) {
|
public boolean declarationsMatchByParameterCount(@NotNull JetProperty a, @NotNull JetProperty b) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user