From fb7fe81a85da70566eb670372952394d44980df1 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 25 Dec 2014 22:01:57 +0300 Subject: [PATCH] Support navigation to dangling annotations in the IDE --- .../jet/lang/resolve/lazy/ResolveSession.java | 29 ++++++++++--- .../lazy/descriptors/LazyClassDescriptor.java | 43 +++++++++++++------ .../lang/resolve/lazy/ElementResolver.java | 37 ++++++++++------ .../jet/plugin/references/JetReference.kt | 3 +- 4 files changed, 77 insertions(+), 35 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java index 40fcca3ce03..0fb5f9e3380 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java @@ -62,7 +62,8 @@ public class ResolveSession implements KotlinCodeAnalyzer { private final MemoizedFunctionToNotNull scriptDescriptors; - private final MemoizedFunctionToNotNull annotations; + private final MemoizedFunctionToNotNull fileAnnotations; + private final MemoizedFunctionToNotNull danglingAnnotations; private ScopeProvider scopeProvider; @@ -168,14 +169,25 @@ public class ResolveSession implements KotlinCodeAnalyzer { } ); - annotations = storageManager.createMemoizedFunction(new Function1() { + fileAnnotations = storageManager.createMemoizedFunction(new Function1() { @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() { + @Override + public LazyAnnotations invoke(JetFile file) { + return createAnnotations(file, file.getDanglingAnnotations()); + } + }); + } + + private LazyAnnotations createAnnotations(JetFile file, List 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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassDescriptor.java index 9a2a456f0ad..9dd1e93ad3b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -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 classObjectDescriptor; private final MemoizedFunctionToNotNull extraClassObjectDescriptors; @@ -95,8 +96,6 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes private final NotNullLazyValue scopeForMemberDeclarationResolution; private final NotNullLazyValue scopeForPropertyInitializerResolution; - private final NullableLazyValue resolveDanglingAnnotations; - private final NullableLazyValue 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 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() { @Override public LazyClassDescriptor invoke() { @@ -192,15 +212,6 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes return computeScopeForPropertyInitializerResolution(); } }); - this.resolveDanglingAnnotations = storageManager.createNullableLazyValue(new Function0() { - @Override - public Void invoke() { - resolveSession.getAnnotationResolver().resolveAnnotationsWithArguments( - getScopeForMemberDeclarationResolution(), originalClassInfo.getDanglingAnnotations(), resolveSession.getTrace() - ); - return null; - } - }); this.forceResolveAllContents = storageManager.createRecursionTolerantNullableLazyValue(new Function0() { @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(); diff --git a/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/ElementResolver.java b/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/ElementResolver.java index bd2c0a5a235..785a4c22740 100644 --- a/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/ElementResolver.java +++ b/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/ElementResolver.java @@ -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) { diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/references/JetReference.kt b/idea/idea-analysis/src/org/jetbrains/jet/plugin/references/JetReference.kt index 1c0b313bfe6..58e034cbd5b 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/references/JetReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/references/JetReference.kt @@ -72,7 +72,8 @@ public abstract class AbstractJetReference(element: T) override fun isSoft(): Boolean = false private fun resolveToPsiElements(): Collection { - return resolveToPsiElements(expression.analyze(), getTargetDescriptors(expression.analyze())) + val bindingContext = expression.analyze() + return resolveToPsiElements(bindingContext, getTargetDescriptors(bindingContext)) } override fun resolveToDescriptors(): Collection {