From 6158c306902c4e3f2a0fab14073f2ca14918256c Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 6 Sep 2011 17:58:18 +0400 Subject: [PATCH] Annotation resolver beautified a bit --- .../descriptors/MutableClassDescriptor.java | 1 - .../jet/lang/psi/JetModifierList.java | 4 +- .../jet/lang/resolve/AnnotationResolver.java | 24 +++++-- .../jet/lang/resolve/BindingContext.java | 2 + .../jet/lang/resolve/BindingTrace.java | 2 + .../jet/lang/resolve/TopDownAnalyzer.java | 47 ++++++++++-- .../jet/lang/resolve/calls/CallResolver.java | 71 ++++++++++--------- .../jet/lang/types/JetTypeInferrer.java | 4 ++ 8 files changed, 108 insertions(+), 47 deletions(-) diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java index 1ea669ae48d..9161d9b0014 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -176,7 +176,6 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme supertypes); scopeForMemberResolution.setThisType(getDefaultType()); for (FunctionDescriptor functionDescriptor : constructors.getFunctionDescriptors()) { -// functionDescriptor.getTypeParameters().addAll(typeParameters); ((ConstructorDescriptorImpl) functionDescriptor).setReturnType(getDefaultType()); } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java b/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java index 8cfbe02064b..2c5e47472c5 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.lang.psi; +import com.google.common.collect.Lists; import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,7 +35,8 @@ public class JetModifierList extends JetElement { } public List getAnnotationEntries() { - List answer = null; + List entries = findChildrenByType(JetNodeTypes.ANNOTATION_ENTRY); + List answer = entries.isEmpty() ? null : Lists.newArrayList(entries); for (JetAnnotation annotation : getAnnotations()) { if (answer == null) answer = new ArrayList(); answer.addAll(annotation.getEntries()); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index 45b58351814..20506d72c01 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -4,25 +4,31 @@ import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; +import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.JetAnnotationEntry; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetModifierList; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.JetTypeInferrer; import java.util.Collections; import java.util.List; +import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE; + /** * @author abreslav */ public class AnnotationResolver { private final BindingTrace trace; + private final JetTypeInferrer typeInferrer; public AnnotationResolver(JetSemanticServices semanticServices, BindingTrace trace) { - + this.typeInferrer = new JetTypeInferrer(JetFlowInformationProvider.THROW_EXCEPTION, semanticServices); this.trace = trace; } @@ -30,15 +36,19 @@ public class AnnotationResolver { public List resolveAnnotations(@NotNull JetScope scope, @NotNull List annotationEntryElements) { if (annotationEntryElements.isEmpty()) return Collections.emptyList(); List result = Lists.newArrayList(); -// for (JetAnnotationEntry entryElement : annotationEntryElements) { -// JetType jetType = typeInferrer.checkTypeInitializerCall(scope, entryElement.getTypeReference(), entryElement); -// AnnotationDescriptor descriptor = new AnnotationDescriptor(); -// descriptor.setAnnotationType(jetType); -// result.add(descriptor); -// } + for (JetAnnotationEntry entryElement : annotationEntryElements) { + AnnotationDescriptor descriptor = new AnnotationDescriptor(); + resolveAnnotationStub(scope, entryElement, descriptor); + result.add(descriptor); + } return result; } + public void resolveAnnotationStub(@NotNull JetScope scope, @NotNull JetAnnotationEntry entryElement, @NotNull AnnotationDescriptor descriptor) { + JetType jetType = typeInferrer.getCallResolver().resolveCall(trace, scope, null, entryElement, NO_EXPECTED_TYPE); + descriptor.setAnnotationType(jetType == null ? ErrorUtils.createErrorType("Unresolved annotation type") : jetType); + } + @NotNull public List resolveAnnotations(@NotNull JetScope scope, @Nullable JetModifierList modifierList) { if (modifierList == null) { diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java index 51cf3bfda56..206ca3cd8df 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.resolve; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetDiagnostic; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; @@ -112,5 +113,6 @@ public interface BindingContext { Collection getDiagnostics(); + @Nullable V get(ReadOnlySlice slice, K key); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java index cf5f3b395fc..393a7645812 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.resolve; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.ErrorHandler; import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; import org.jetbrains.jet.util.slicedmap.WritableSlice; @@ -20,5 +21,6 @@ public interface BindingTrace { // Writes TRUE for a boolean value void record(WritableSlice slice, K key); + @Nullable V get(ReadOnlySlice slice, K key); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index da417c31e67..d8f9234e2a5 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -17,6 +17,7 @@ import org.jetbrains.jet.util.slicedmap.WritableSlice; import java.util.*; +import static org.jetbrains.jet.lang.resolve.BindingContext.ANNOTATION; import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE; /** @@ -40,6 +41,7 @@ public class TopDownAnalyzer { private final BindingTrace trace; private final BindingTraceAdapter traceForConstructors; private final BindingTraceAdapter traceForMembers; + private final AnnotationResolver annotationResolver; public TopDownAnalyzer(JetSemanticServices semanticServices, @NotNull BindingTrace bindingTrace) { this.semanticServices = semanticServices; @@ -73,6 +75,8 @@ public class TopDownAnalyzer { } } }); + + this.annotationResolver = new AnnotationResolver(semanticServices, trace); } public void processObject(@NotNull JetScope outerScope, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetObjectDeclaration object) { @@ -117,7 +121,11 @@ public class TopDownAnalyzer { resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution) checkGenericBoundsInClassHeaders(); // For the types resolved so far - resolveFunctionAndPropertyHeaders(); // Constructor headers are resolved as well + resolveConstructorHeaders(); + + resolveAnnotationStubsOnClassesAndConstructors(); + + resolveFunctionAndPropertyHeaders(); resolveBehaviorDeclarationBodies(); } @@ -372,6 +380,35 @@ public class TopDownAnalyzer { } } + private void resolveConstructorHeaders() { + for (Map.Entry entry : classes.entrySet()) { + JetClass jetClass = entry.getKey(); + MutableClassDescriptor classDescriptor = entry.getValue(); + + processPrimaryConstructor(classDescriptor, jetClass); + for (JetConstructor jetConstructor : jetClass.getSecondaryConstructors()) { + processSecondaryConstructor(classDescriptor, jetConstructor); + } + } + + } + + private void resolveAnnotationStubsOnClassesAndConstructors() { + for (Map.Entry entry : classes.entrySet()) { + JetClass jetClass = entry.getKey(); + MutableClassDescriptor mutableClassDescriptor = entry.getValue(); + + JetModifierList modifierList = jetClass.getModifierList(); + if (modifierList != null) { + List annotationEntries = modifierList.getAnnotationEntries(); + for (JetAnnotationEntry annotationEntry : annotationEntries) { + AnnotationDescriptor annotationDescriptor = trace.get(ANNOTATION, annotationEntry); + annotationResolver.resolveAnnotationStub(mutableClassDescriptor.getScopeForSupertypeResolution(), annotationEntry, annotationDescriptor); + } + } + } + } + private void resolveFunctionAndPropertyHeaders() { for (Map.Entry entry : namespaceScopes.entrySet()) { JetNamespace namespace = entry.getKey(); @@ -385,10 +422,10 @@ public class TopDownAnalyzer { MutableClassDescriptor classDescriptor = entry.getValue(); resolveFunctionAndPropertyHeaders(jetClass.getDeclarations(), classDescriptor.getScopeForMemberResolution(), classDescriptor); - processPrimaryConstructor(classDescriptor, jetClass); - for (JetConstructor jetConstructor : jetClass.getSecondaryConstructors()) { - processSecondaryConstructor(classDescriptor, jetConstructor); - } +// processPrimaryConstructor(classDescriptor, jetClass); +// for (JetConstructor jetConstructor : jetClass.getSecondaryConstructors()) { +// processSecondaryConstructor(classDescriptor, jetConstructor); +// } } for (Map.Entry entry : objects.entrySet()) { JetObjectDeclaration object = entry.getKey(); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 062cd490308..0f681833fe6 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -98,49 +98,54 @@ public class CallResolver { prioritizedTasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiverType, call, name); } - else if (calleeExpression instanceof JetConstructorCalleeExpression) { - assert receiverType == null; + else { + JetValueArgumentList valueArgumentList = call.getValueArgumentList(); + ASTNode reportAbsenceOn = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode(); + if (calleeExpression instanceof JetConstructorCalleeExpression) { + assert receiverType == null; - prioritizedTasks = Lists.newArrayList(); + prioritizedTasks = Lists.newArrayList(); - JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression; - functionReference = expression.getConstructorReferenceExpression(); - if (functionReference == null) { - return checkArgumentTypesAndFail(trace, scope, call); // No type there + JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression; + functionReference = expression.getConstructorReferenceExpression(); + if (functionReference == null) { + return checkArgumentTypesAndFail(trace, scope, call); // No type there + } + JetTypeReference typeReference = expression.getTypeReference(); + assert typeReference != null; + JetType constructedType = new TypeResolver(semanticServices, trace, true).resolveType(scope, typeReference); + DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor(); + if (declarationDescriptor instanceof ClassDescriptor) { + ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; + Set constructors = classDescriptor.getConstructors().getFunctionDescriptors(); + if (constructors.isEmpty()) { + trace.getErrorHandler().genericError(reportAbsenceOn, "This class does not have a constructor"); + return checkArgumentTypesAndFail(trace, scope, call); + } + prioritizedTasks.add(new ResolutionTask(constructors, null, call)); + } + else { + trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class"); + return checkArgumentTypesAndFail(trace, scope, call); + } } - JetTypeReference typeReference = expression.getTypeReference(); - assert typeReference != null; - JetType constructedType = new TypeResolver(semanticServices, trace, true).resolveType(scope, typeReference); - DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor(); - if (declarationDescriptor instanceof ClassDescriptor) { - ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; + else if (calleeExpression instanceof JetThisReferenceExpression) { + functionReference = (JetThisReferenceExpression) calleeExpression; + DeclarationDescriptor containingDeclaration = scope.getContainingDeclaration(); + assert containingDeclaration instanceof ClassDescriptor; + ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; + + Set constructors = classDescriptor.getConstructors().getFunctionDescriptors(); if (constructors.isEmpty()) { - trace.getErrorHandler().genericError(call.getValueArgumentList().getNode(), "This class does not have a constructor"); + trace.getErrorHandler().genericError(reportAbsenceOn, "This class does not have a constructor"); return checkArgumentTypesAndFail(trace, scope, call); } - prioritizedTasks.add(new ResolutionTask(constructors, null, call)); + prioritizedTasks = Collections.singletonList(new ResolutionTask(constructors, null, call)); } else { - trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class"); - return checkArgumentTypesAndFail(trace, scope, call); + throw new UnsupportedOperationException("Type argument inference not implemented for " + call.getText()); } - } else if (calleeExpression instanceof JetThisReferenceExpression) { - functionReference = (JetThisReferenceExpression) calleeExpression; - DeclarationDescriptor containingDeclaration = scope.getContainingDeclaration(); - assert containingDeclaration instanceof ClassDescriptor; - ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; - - - Set constructors = classDescriptor.getConstructors().getFunctionDescriptors(); - if (constructors.isEmpty()) { - trace.getErrorHandler().genericError(call.getValueArgumentList().getNode(), "This class does not have a constructor"); - return checkArgumentTypesAndFail(trace, scope, call); - } - prioritizedTasks = Collections.singletonList(new ResolutionTask(constructors, null, call)); - } - else { - throw new UnsupportedOperationException("Type argument inference not implemented for " + call.getText()); } return resolveCallToDescriptor(trace, scope, call, call.getNode(), expectedType, prioritizedTasks, functionReference); diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 4a5a91d4103..2d474001963 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -170,6 +170,10 @@ public class JetTypeInferrer { return new Services(trace); } + public CallResolver getCallResolver() { + return callResolver; + } + public class Services { private final BindingTrace trace; private final CompileTimeConstantResolver compileTimeConstantResolver; -- GitLab