Resolve dangling annotations in files and class bodies
This commit is contained in:
@@ -19,6 +19,8 @@ package org.jetbrains.jet.lang.psi;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
@@ -83,4 +85,19 @@ public class JetClassBody extends JetElementImplStub<KotlinPlaceHolderStub<JetCl
|
||||
ASTNode[] children = getNode().getChildren(TokenSet.create(JetTokens.LBRACE));
|
||||
return children.length == 1 ? children[0].getPsi() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return annotations that do not belong to any declaration due to incomplete code or syntax errors
|
||||
*/
|
||||
@NotNull
|
||||
public List<JetAnnotationEntry> getDanglingAnnotations() {
|
||||
return KotlinPackage.flatMap(
|
||||
findChildrenByClass(JetModifierList.class),
|
||||
new Function1<JetModifierList, Iterable<JetAnnotationEntry>>() {
|
||||
@Override
|
||||
public Iterable<JetAnnotationEntry> invoke(JetModifierList modifierList) {
|
||||
return modifierList.getAnnotationEntries();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ import com.intellij.psi.PsiClassOwner;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
@@ -237,4 +239,19 @@ public class JetFile extends PsiFileBase implements JetDeclarationContainer, Jet
|
||||
|
||||
return fileAnnotationList.getAnnotationEntries();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return annotations that do not belong to any declaration due to incomplete code or syntax errors
|
||||
*/
|
||||
@NotNull
|
||||
public List<JetAnnotationEntry> getDanglingAnnotations() {
|
||||
return KotlinPackage.flatMap(
|
||||
findChildrenByClass(JetModifierList.class),
|
||||
new Function1<JetModifierList, Iterable<JetAnnotationEntry>>() {
|
||||
@Override
|
||||
public Iterable<JetAnnotationEntry> invoke(JetModifierList modifierList) {
|
||||
return modifierList.getAnnotationEntries();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,13 +51,9 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.REDECLARATION;
|
||||
import static org.jetbrains.jet.lang.resolve.ScriptHeaderResolver.resolveScriptDeclarations;
|
||||
|
||||
public class DeclarationResolver {
|
||||
@NotNull
|
||||
private AnnotationResolver annotationResolver;
|
||||
@NotNull
|
||||
private ImportsResolver importsResolver;
|
||||
@NotNull
|
||||
private DescriptorResolver descriptorResolver;
|
||||
@NotNull
|
||||
private BindingTrace trace;
|
||||
|
||||
|
||||
@@ -87,6 +83,7 @@ public class DeclarationResolver {
|
||||
resolveConstructorHeaders(c);
|
||||
resolveAnnotationStubsOnClassesAndConstructors(c);
|
||||
resolveFunctionAndPropertyHeaders(c);
|
||||
resolveDanglingAnnotationsInClasses(c);
|
||||
resolveAnnotationsOnFiles(c.getFileScopes());
|
||||
|
||||
// SCRIPT: Resolve script declarations
|
||||
@@ -115,6 +112,7 @@ public class DeclarationResolver {
|
||||
JetFile file = entry.getKey();
|
||||
JetScope fileScope = entry.getValue();
|
||||
annotationResolver.resolveAnnotationsWithArguments(fileScope, file.getAnnotationEntries(), trace);
|
||||
annotationResolver.resolveAnnotationsWithArguments(fileScope, file.getDanglingAnnotations(), trace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,6 +220,19 @@ public class DeclarationResolver {
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveDanglingAnnotationsInClasses(TopDownAnalysisContext c) {
|
||||
for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
|
||||
JetClassBody body = entry.getKey().getBody();
|
||||
if (body != null) {
|
||||
annotationResolver.resolveAnnotationsWithArguments(
|
||||
entry.getValue().getScopeForMemberDeclarationResolution(),
|
||||
body.getDanglingAnnotations(),
|
||||
trace
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createFunctionsForDataClasses(@NotNull TopDownAnalysisContext c) {
|
||||
for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
|
||||
JetClassOrObject klass = entry.getKey();
|
||||
|
||||
@@ -44,41 +44,23 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.MANY_CLASS_OBJECTS;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.UNSUPPORTED;
|
||||
|
||||
public class LazyTopDownAnalyzer {
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull
|
||||
private BindingTrace trace = null;
|
||||
private BindingTrace trace;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull
|
||||
private DeclarationResolver declarationResolver = null;
|
||||
private DeclarationResolver declarationResolver;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull
|
||||
private OverrideResolver overrideResolver = null;
|
||||
private OverrideResolver overrideResolver;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull
|
||||
private OverloadResolver overloadResolver = null;
|
||||
private OverloadResolver overloadResolver;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull
|
||||
private VarianceChecker varianceChecker = null;
|
||||
private VarianceChecker varianceChecker;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull
|
||||
private ModuleDescriptor moduleDescriptor = null;
|
||||
private ModuleDescriptor moduleDescriptor;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull
|
||||
private KotlinCodeAnalyzer resolveSession = null;
|
||||
private KotlinCodeAnalyzer resolveSession;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull
|
||||
private BodyResolver bodyResolver = null;
|
||||
private BodyResolver bodyResolver;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull
|
||||
private TopDownAnalyzer topDownAnalyzer = null;
|
||||
private TopDownAnalyzer topDownAnalyzer;
|
||||
|
||||
@Inject
|
||||
public void setKotlinCodeAnalyzer(@NotNull KotlinCodeAnalyzer kotlinCodeAnalyzer) {
|
||||
|
||||
@@ -57,4 +57,6 @@ public interface JetClassLikeInfo extends JetDeclarationContainer {
|
||||
@NotNull
|
||||
ClassKind getClassKind();
|
||||
|
||||
@NotNull
|
||||
List<JetAnnotationEntry> getDanglingAnnotations();
|
||||
}
|
||||
|
||||
+7
@@ -77,6 +77,13 @@ public abstract class JetClassOrObjectInfo<E extends JetClassOrObject> implement
|
||||
throw new IllegalArgumentException("Not in a JetFile: " + element);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetAnnotationEntry> getDanglingAnnotations() {
|
||||
JetClassBody body = element.getBody();
|
||||
return body == null ? Collections.<JetAnnotationEntry>emptyList() : body.getDanglingAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "info for " + element.getText();
|
||||
|
||||
@@ -36,6 +36,7 @@ public class JetScriptInfo(
|
||||
override fun getClassKind() = ClassKind.CLASS
|
||||
override fun getDeclarations() = script.getDeclarations()
|
||||
.filter(::shouldBeScriptClassMember)
|
||||
override fun getDanglingAnnotations() = listOf<JetAnnotationEntry>()
|
||||
}
|
||||
|
||||
public fun shouldBeScriptClassMember(declaration: JetDeclaration): Boolean {
|
||||
|
||||
+6
@@ -96,6 +96,12 @@ public class SyntheticClassObjectInfo implements JetClassLikeInfo {
|
||||
return ClassKind.CLASS_OBJECT;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetAnnotationEntry> getDanglingAnnotations() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetDeclaration> getDeclarations() {
|
||||
|
||||
+13
@@ -95,6 +95,8 @@ 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(
|
||||
@@ -190,6 +192,15 @@ 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() {
|
||||
@@ -448,6 +459,8 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
||||
public void resolveMemberHeaders() {
|
||||
ForceResolveUtil.forceResolveAllContents(getAnnotations());
|
||||
|
||||
resolveDanglingAnnotations.invoke();
|
||||
|
||||
getClassObjectDescriptor();
|
||||
|
||||
getDescriptorsForExtraClassObjects();
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
annotation class Ann
|
||||
annotation class Ann2
|
||||
|
||||
class C {
|
||||
fun foo() {
|
||||
class Local {
|
||||
<!UNRESOLVED_REFERENCE!>Ann0<!>
|
||||
[Ann <!UNRESOLVED_REFERENCE!>Ann3<!>]
|
||||
Ann2(<!TOO_MANY_ARGUMENTS!>1<!>)
|
||||
[<!UNRESOLVED_REFERENCE!>Ann4<!>]<!SYNTAX!><!>
|
||||
}
|
||||
}
|
||||
<!UNRESOLVED_REFERENCE!>Ann0<!>
|
||||
[Ann <!UNRESOLVED_REFERENCE!>Ann3<!>]
|
||||
Ann2(<!TOO_MANY_ARGUMENTS!>1<!>)
|
||||
[<!UNRESOLVED_REFERENCE!>Ann4<!>]<!SYNTAX!><!>
|
||||
}
|
||||
|
||||
<!UNRESOLVED_REFERENCE!>Ann0<!>
|
||||
[Ann <!UNRESOLVED_REFERENCE!>Ann3<!>]
|
||||
Ann2(<!TOO_MANY_ARGUMENTS!>1<!>)
|
||||
[<!UNRESOLVED_REFERENCE!>Ann4<!>]<!SYNTAX!><!>
|
||||
@@ -0,0 +1,23 @@
|
||||
package
|
||||
|
||||
internal final annotation class Ann : kotlin.Annotation {
|
||||
public constructor Ann()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal final annotation class Ann2 : kotlin.Annotation {
|
||||
public constructor Ann2()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal final class C {
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
internal final fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
annotation class Ann
|
||||
|
||||
class C {
|
||||
fun foo() {
|
||||
class Local {
|
||||
Ann<!SYNTAX!><!>
|
||||
}
|
||||
}
|
||||
|
||||
Ann<!SYNTAX!><!>
|
||||
}
|
||||
|
||||
Ann<!SYNTAX!><!>
|
||||
@@ -0,0 +1,16 @@
|
||||
package
|
||||
|
||||
internal final annotation class Ann : kotlin.Annotation {
|
||||
public constructor Ann()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal final class C {
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
internal final fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
annotation class Ann
|
||||
|
||||
class C {
|
||||
fun test() {
|
||||
[Ann]<!SYNTAX!><!>
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
class Local {
|
||||
[Ann]<!SYNTAX!><!>
|
||||
}
|
||||
}
|
||||
[Ann]<!SYNTAX!><!>
|
||||
}
|
||||
|
||||
[Ann]<!SYNTAX!><!>
|
||||
@@ -0,0 +1,17 @@
|
||||
package
|
||||
|
||||
internal final annotation class Ann : kotlin.Annotation {
|
||||
public constructor Ann()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal final class C {
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
internal final fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
internal final fun test(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -637,6 +637,24 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DanglingMixed.kt")
|
||||
public void testDanglingMixed() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/DanglingMixed.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DanglingNoBrackets.kt")
|
||||
public void testDanglingNoBrackets() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/DanglingNoBrackets.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DanglingWithBrackets.kt")
|
||||
public void testDanglingWithBrackets() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/DanglingWithBrackets.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Deprecated.kt")
|
||||
public void testDeprecated() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/Deprecated.kt");
|
||||
|
||||
Reference in New Issue
Block a user