Support navigation to dangling annotations in the IDE

This commit is contained in:
Andrey Breslav
2014-12-25 22:01:57 +03:00
parent 89e1588e13
commit fb7fe81a85
4 changed files with 77 additions and 35 deletions
@@ -62,7 +62,8 @@ public class ResolveSession implements KotlinCodeAnalyzer {
private final MemoizedFunctionToNotNull<JetScript, LazyScriptDescriptor> scriptDescriptors;
private final MemoizedFunctionToNotNull<JetFile, LazyAnnotations> annotations;
private final MemoizedFunctionToNotNull<JetFile, LazyAnnotations> fileAnnotations;
private final MemoizedFunctionToNotNull<JetFile, LazyAnnotations> danglingAnnotations;
private ScopeProvider scopeProvider;
@@ -168,14 +169,25 @@ public class ResolveSession implements KotlinCodeAnalyzer {
}
);
annotations = storageManager.createMemoizedFunction(new Function1<JetFile, LazyAnnotations>() {
fileAnnotations = storageManager.createMemoizedFunction(new Function1<JetFile, LazyAnnotations>() {
@Override
public LazyAnnotations invoke(JetFile file) {
JetScope scope = getScopeProvider().getFileScope(file);
LazyAnnotationsContextImpl lazyAnnotationContext = new LazyAnnotationsContextImpl(annotationResolve, storageManager, trace, scope);
return new LazyAnnotations(lazyAnnotationContext, file.getAnnotationEntries());
return createAnnotations(file, file.getAnnotationEntries());
}
});
danglingAnnotations = storageManager.createMemoizedFunction(new Function1<JetFile, LazyAnnotations>() {
@Override
public LazyAnnotations invoke(JetFile file) {
return createAnnotations(file, file.getDanglingAnnotations());
}
});
}
private LazyAnnotations createAnnotations(JetFile file, List<JetAnnotationEntry> annotationEntries) {
JetScope scope = getScopeProvider().getFileScope(file);
LazyAnnotationsContextImpl lazyAnnotationContext = new LazyAnnotationsContextImpl(annotationResolve, storageManager, trace, scope);
return new LazyAnnotations(lazyAnnotationContext, annotationEntries);
}
@Override
@@ -448,7 +460,12 @@ public class ResolveSession implements KotlinCodeAnalyzer {
@NotNull
public Annotations getFileAnnotations(@NotNull JetFile file) {
return annotations.invoke(file);
return fileAnnotations.invoke(file);
}
@NotNull
public Annotations getDanglingAnnotations(@NotNull JetFile file) {
return danglingAnnotations.invoke(file);
}
@NotNull
@@ -85,6 +85,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
private final boolean isInner;
private final Annotations annotations;
private final Annotations danglingAnnotations;
private final NullableLazyValue<LazyClassDescriptor> classObjectDescriptor;
private final MemoizedFunctionToNotNull<JetClassObject, ClassDescriptor> extraClassObjectDescriptors;
@@ -95,8 +96,6 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
private final NotNullLazyValue<JetScope> scopeForMemberDeclarationResolution;
private final NotNullLazyValue<JetScope> scopeForPropertyInitializerResolution;
private final NullableLazyValue<Void> resolveDanglingAnnotations;
private final NullableLazyValue<Void> forceResolveAllContents;
public LazyClassDescriptor(
@@ -144,7 +143,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
this.annotations = new LazyAnnotations(
new LazyAnnotationsContext(
resolveSession.getAnnotationResolver(),
resolveSession.getStorageManager(),
storageManager,
resolveSession.getTrace()
) {
@NotNull
@@ -162,6 +161,27 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
this.annotations = Annotations.EMPTY;
}
List<JetAnnotationEntry> jetDanglingAnnotations = classLikeInfo.getDanglingAnnotations();
if (jetDanglingAnnotations.isEmpty()) {
this.danglingAnnotations = Annotations.EMPTY;
}
else {
this.danglingAnnotations = new LazyAnnotations(
new LazyAnnotationsContext(
resolveSession.getAnnotationResolver(),
storageManager,
resolveSession.getTrace()
) {
@NotNull
@Override
public JetScope getScope() {
return getScopeForMemberDeclarationResolution();
}
},
jetDanglingAnnotations
);
}
this.classObjectDescriptor = storageManager.createNullableLazyValue(new Function0<LazyClassDescriptor>() {
@Override
public LazyClassDescriptor invoke() {
@@ -192,15 +212,6 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
return computeScopeForPropertyInitializerResolution();
}
});
this.resolveDanglingAnnotations = storageManager.createNullableLazyValue(new Function0<Void>() {
@Override
public Void invoke() {
resolveSession.getAnnotationResolver().resolveAnnotationsWithArguments(
getScopeForMemberDeclarationResolution(), originalClassInfo.getDanglingAnnotations(), resolveSession.getTrace()
);
return null;
}
});
this.forceResolveAllContents = storageManager.createRecursionTolerantNullableLazyValue(new Function0<Void>() {
@Override
public Void invoke() {
@@ -431,6 +442,11 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
return annotations;
}
@NotNull
public Annotations getDanglingAnnotations() {
return danglingAnnotations;
}
@Override
public String toString() {
// not using descriptor render to preserve laziness
@@ -458,8 +474,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
// Note: headers of member classes' members are not resolved
public void resolveMemberHeaders() {
ForceResolveUtil.forceResolveAllContents(getAnnotations());
resolveDanglingAnnotations.invoke();
ForceResolveUtil.forceResolveAllContents(getDanglingAnnotations());
getClassObjectDescriptor();
@@ -287,24 +287,25 @@ public abstract class ElementResolver {
}
private static void annotationAdditionalResolve(ResolveSession resolveSession, JetAnnotationEntry jetAnnotationEntry) {
Annotations annotations = null;
JetModifierList modifierList = PsiTreeUtil.getParentOfType(jetAnnotationEntry, JetModifierList.class);
JetDeclaration declaration = PsiTreeUtil.getParentOfType(modifierList, JetDeclaration.class);
if (declaration != null) {
annotations = getAnnotationsByDeclaration(resolveSession, modifierList, declaration);
doResolveAnnotations(resolveSession, getAnnotationsByDeclaration(resolveSession, modifierList, declaration));
}
else {
JetFileAnnotationList fileAnnotationList = PsiTreeUtil.getParentOfType(jetAnnotationEntry, JetFileAnnotationList.class);
if (fileAnnotationList != null) {
annotations = resolveSession.getFileAnnotations(fileAnnotationList.getContainingJetFile());
doResolveAnnotations(resolveSession, resolveSession.getFileAnnotations(fileAnnotationList.getContainingJetFile()));
}
if (modifierList != null && modifierList.getParent() instanceof JetFile) {
doResolveAnnotations(resolveSession, resolveSession.getDanglingAnnotations(modifierList.getContainingJetFile()));
}
}
}
if (annotations != null) {
AnnotationResolver.resolveAnnotationsArguments(annotations, resolveSession.getTrace());
ForceResolveUtil.forceResolveAllContents(annotations);
}
private static void doResolveAnnotations(ResolveSession resolveSession, Annotations annotations) {
AnnotationResolver.resolveAnnotationsArguments(annotations, resolveSession.getTrace());
ForceResolveUtil.forceResolveAllContents(annotations);
}
private static Annotations getAnnotationsByDeclaration(
@@ -312,13 +313,21 @@ public abstract class ElementResolver {
JetModifierList modifierList,
JetDeclaration declaration
) {
Annotations annotations;Annotated descriptor = resolveSession.resolveToDescriptor(declaration);
if (declaration instanceof JetClass && modifierList == ((JetClass) declaration).getPrimaryConstructorModifierList()) {
descriptor = ((ClassDescriptor)descriptor).getUnsubstitutedPrimaryConstructor();
assert descriptor != null : "No constructor found: " + declaration.getText();
Annotated descriptor = resolveSession.resolveToDescriptor(declaration);
if (declaration instanceof JetClass) {
JetClass jetClass = (JetClass) declaration;
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
if (modifierList == jetClass.getPrimaryConstructorModifierList()) {
descriptor = classDescriptor.getUnsubstitutedPrimaryConstructor();
assert descriptor != null : "No constructor found: " + declaration.getText();
}
else if (modifierList.getParent() == jetClass.getBody()) {
if (classDescriptor instanceof LazyClassDescriptor) {
return ((LazyClassDescriptor) classDescriptor).getDanglingAnnotations();
}
}
}
annotations = descriptor.getAnnotations();
return annotations;
return descriptor.getAnnotations();
}
private static void typeParameterAdditionalResolve(KotlinCodeAnalyzer analyzer, JetTypeParameter typeParameter) {
@@ -72,7 +72,8 @@ public abstract class AbstractJetReference<T : JetElement>(element: T)
override fun isSoft(): Boolean = false
private fun resolveToPsiElements(): Collection<PsiElement> {
return resolveToPsiElements(expression.analyze(), getTargetDescriptors(expression.analyze()))
val bindingContext = expression.analyze()
return resolveToPsiElements(bindingContext, getTargetDescriptors(bindingContext))
}
override fun resolveToDescriptors(): Collection<DeclarationDescriptor> {