diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index 7bd46ce35e7..cc1d90358f5 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -181,6 +181,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.topDownAnalysisContext.setTopDownAnalysisParameters(topDownAnalysisParameters); + this.bodyResolver.setAnnotationResolver(annotationResolver); this.bodyResolver.setCallResolver(callResolver); this.bodyResolver.setContext(topDownAnalysisContext); this.bodyResolver.setControlFlowAnalyzer(controlFlowAnalyzer); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java index 9926b81519a..ac6bb8a5ad6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java @@ -23,12 +23,12 @@ import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BodiesResolveContext; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; +import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.DescriptorResolver; -import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.TypeResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CandidateResolver; @@ -49,12 +49,12 @@ public class InjectorForBodyResolve { private final BindingTrace bindingTrace; private final BodiesResolveContext bodiesResolveContext; private final ModuleDescriptor moduleDescriptor; + private AnnotationResolver annotationResolver; private CallResolver callResolver; private ArgumentTypeResolver argumentTypeResolver; private ExpressionTypingServices expressionTypingServices; private CallExpressionResolver callExpressionResolver; private DescriptorResolver descriptorResolver; - private AnnotationResolver annotationResolver; private TypeResolver typeResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; private CandidateResolver candidateResolver; @@ -77,12 +77,12 @@ public class InjectorForBodyResolve { this.bindingTrace = bindingTrace; this.bodiesResolveContext = bodiesResolveContext; this.moduleDescriptor = moduleDescriptor; + this.annotationResolver = new AnnotationResolver(); this.callResolver = new CallResolver(); this.argumentTypeResolver = new ArgumentTypeResolver(); this.expressionTypingServices = new ExpressionTypingServices(); this.callExpressionResolver = new CallExpressionResolver(); this.descriptorResolver = new DescriptorResolver(); - this.annotationResolver = new AnnotationResolver(); this.typeResolver = new TypeResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.candidateResolver = new CandidateResolver(); @@ -91,6 +91,7 @@ public class InjectorForBodyResolve { this.scriptBodyResolver = new ScriptBodyResolver(); this.topDownAnalysisContext = new TopDownAnalysisContext(); + this.bodyResolver.setAnnotationResolver(annotationResolver); this.bodyResolver.setCallResolver(callResolver); this.bodyResolver.setContext(bodiesResolveContext); this.bodyResolver.setControlFlowAnalyzer(controlFlowAnalyzer); @@ -101,6 +102,9 @@ public class InjectorForBodyResolve { this.bodyResolver.setTopDownAnalysisParameters(topDownAnalysisParameters); this.bodyResolver.setTrace(bindingTrace); + annotationResolver.setCallResolver(callResolver); + annotationResolver.setExpressionTypingServices(expressionTypingServices); + callResolver.setArgumentTypeResolver(argumentTypeResolver); callResolver.setCandidateResolver(candidateResolver); callResolver.setExpressionTypingServices(expressionTypingServices); @@ -122,9 +126,6 @@ public class InjectorForBodyResolve { descriptorResolver.setExpressionTypingServices(expressionTypingServices); descriptorResolver.setTypeResolver(typeResolver); - annotationResolver.setCallResolver(callResolver); - annotationResolver.setExpressionTypingServices(expressionTypingServices); - typeResolver.setAnnotationResolver(annotationResolver); typeResolver.setDescriptorResolver(descriptorResolver); typeResolver.setModuleDescriptor(moduleDescriptor); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java index 966d52b828c..5e1e7e47cd7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java @@ -130,6 +130,7 @@ public class InjectorForTopDownAnalyzerBasic { this.topDownAnalysisContext.setTopDownAnalysisParameters(topDownAnalysisParameters); + this.bodyResolver.setAnnotationResolver(annotationResolver); this.bodyResolver.setCallResolver(callResolver); this.bodyResolver.setContext(topDownAnalysisContext); this.bodyResolver.setControlFlowAnalyzer(controlFlowAnalyzer); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index 7a6f3bbf5a9..c8345704670 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -20,6 +20,7 @@ import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.annotations.Annotated; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; @@ -40,6 +41,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import static org.jetbrains.jet.lang.resolve.BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT; import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; public class AnnotationResolver { @@ -58,34 +60,56 @@ public class AnnotationResolver { } @NotNull - public List resolveAnnotations(@NotNull JetScope scope, @Nullable JetModifierList modifierList, BindingTrace trace) { - if (modifierList == null) { - return Collections.emptyList(); - } - return resolveAnnotations(scope, modifierList.getAnnotationEntries(), trace); + public List resolveAnnotations( + @NotNull JetScope scope, + @Nullable JetModifierList modifierList, + @NotNull BindingTrace trace) + { + return resolveAnnotations(scope, modifierList, trace, false); } @NotNull - public List resolveAnnotations(@NotNull JetScope scope, @NotNull List annotationEntryElements, BindingTrace trace) { + public List resolveAnnotationsWithArguments( + @NotNull JetScope scope, + @Nullable JetModifierList modifierList, + @NotNull BindingTrace trace + ) { + return resolveAnnotations(scope, modifierList, trace, true); + } + + private List resolveAnnotations( + @NotNull JetScope scope, + @Nullable JetModifierList modifierList, + @NotNull BindingTrace trace, + boolean shouldResolveArguments + ) { + if (modifierList == null) { + return Collections.emptyList(); + } + List annotationEntryElements = modifierList.getAnnotationEntries(); + if (annotationEntryElements.isEmpty()) return Collections.emptyList(); List result = Lists.newArrayList(); for (JetAnnotationEntry entryElement : annotationEntryElements) { AnnotationDescriptor descriptor = new AnnotationDescriptor(); resolveAnnotationStub(scope, entryElement, descriptor, trace); trace.record(BindingContext.ANNOTATION, entryElement, descriptor); + if (shouldResolveArguments) { + resolveAnnotationArguments(entryElement, scope, trace); + } result.add(descriptor); } return result; } - public void resolveAnnotationStub(@NotNull JetScope scope, @NotNull JetAnnotationEntry entryElement, - @NotNull AnnotationDescriptor annotationDescriptor, BindingTrace trace) { - OverloadResolutionResults results = callResolver.resolveFunctionCall( - trace, - scope, - CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, entryElement), - NO_EXPECTED_TYPE, - DataFlowInfo.EMPTY); + public void resolveAnnotationStub( + @NotNull JetScope scope, + @NotNull JetAnnotationEntry entryElement, + @NotNull AnnotationDescriptor annotationDescriptor, + @NotNull BindingTrace trace + ) { + TemporaryBindingTrace temporaryBindingTrace = new TemporaryBindingTrace(trace, "Trace for resolve annotation type"); + OverloadResolutionResults results = resolveAnnotationCall(entryElement, scope, temporaryBindingTrace); if (results.isSuccess()) { FunctionDescriptor descriptor = results.getResultingDescriptor(); if (!ErrorUtils.isError(descriptor)) { @@ -102,27 +126,64 @@ public class AnnotationResolver { } JetType annotationType = results.getResultingDescriptor().getReturnType(); annotationDescriptor.setAnnotationType(annotationType); - resolveArguments(results, annotationDescriptor, trace); } else { annotationDescriptor.setAnnotationType(ErrorUtils.createErrorType("Unresolved annotation type")); } } - private void resolveArguments(@NotNull OverloadResolutionResults results, - @NotNull AnnotationDescriptor descriptor, BindingTrace trace) { - for (Map.Entry descriptorToArgument : - results.getResultingCall().getValueArguments().entrySet()) { - // TODO: are varargs supported here? - List valueArguments = descriptorToArgument.getValue().getArguments(); - ValueParameterDescriptor parameterDescriptor = descriptorToArgument.getKey(); - for (ValueArgument argument : valueArguments) { - JetExpression argumentExpression = argument.getArgumentExpression(); - if (argumentExpression != null) { - CompileTimeConstant compileTimeConstant = - resolveAnnotationArgument(argumentExpression, parameterDescriptor.getType(), trace); - if (compileTimeConstant != null) { - descriptor.setValueArgument(parameterDescriptor, compileTimeConstant); + private OverloadResolutionResults resolveAnnotationCall( + JetAnnotationEntry annotationEntry, + JetScope scope, + BindingTrace trace + ) { + return callResolver.resolveFunctionCall( + trace, scope, + CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, annotationEntry), + NO_EXPECTED_TYPE, + DataFlowInfo.EMPTY); + } + + public void resolveAnnotationsArguments(@NotNull JetScope scope, @Nullable JetModifierList modifierList, @NotNull BindingTrace trace) { + if (modifierList == null) { + return; + } + + for (JetAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) { + resolveAnnotationArguments(annotationEntry, scope, trace); + } + } + + public void resolveAnnotationsArguments(@NotNull Annotated descriptor, @NotNull BindingTrace trace, @NotNull JetScope scope) { + for (AnnotationDescriptor annotationDescriptor : descriptor.getAnnotations()) { + JetAnnotationEntry annotationEntry = trace.getBindingContext().get(ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT, annotationDescriptor); + assert annotationEntry != null : "Cannot find annotation entry: " + annotationDescriptor; + resolveAnnotationArguments(annotationEntry, scope, trace); + } + } + + private void resolveAnnotationArguments( + @NotNull JetAnnotationEntry annotationEntry, + @NotNull JetScope scope, + @NotNull BindingTrace trace + ) { + OverloadResolutionResults results = resolveAnnotationCall(annotationEntry, scope, trace); + if (results.isSuccess()) { + for (Map.Entry descriptorToArgument : + results.getResultingCall().getValueArguments().entrySet()) { + // TODO: are varargs supported here? + List valueArguments = descriptorToArgument.getValue().getArguments(); + ValueParameterDescriptor parameterDescriptor = descriptorToArgument.getKey(); + for (ValueArgument argument : valueArguments) { + JetExpression argumentExpression = argument.getArgumentExpression(); + if (argumentExpression != null) { + CompileTimeConstant compileTimeConstant = + resolveAnnotationArgument(argumentExpression, parameterDescriptor.getType(), trace); + if (compileTimeConstant != null) { + AnnotationDescriptor annotationDescriptor = trace.getBindingContext().get(BindingContext.ANNOTATION, annotationEntry); + assert annotationDescriptor != null : "Annotation descriptor should be created before resolving arguments for " + annotationEntry.getText(); + annotationDescriptor.setValueArgument(parameterDescriptor, compileTimeConstant); + } } } } @@ -130,7 +191,7 @@ public class AnnotationResolver { } @Nullable - public CompileTimeConstant resolveAnnotationArgument(@NotNull JetExpression expression, @NotNull final JetType expectedType, final BindingTrace trace) { + private CompileTimeConstant resolveAnnotationArgument(@NotNull JetExpression expression, @NotNull final JetType expectedType, final BindingTrace trace) { JetVisitor, Void> visitor = new JetVisitor, Void>() { @Override public CompileTimeConstant visitConstantExpression(JetConstantExpression expression, Void nothing) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 02355cdc21d..06013cee778 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -74,6 +74,8 @@ public class BodyResolver { private ControlFlowAnalyzer controlFlowAnalyzer; @NotNull private DeclarationsChecker declarationsChecker; + @NotNull + private AnnotationResolver annotationResolver; @Inject public void setTopDownAnalysisParameters(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) { @@ -120,6 +122,11 @@ public class BodyResolver { this.context = context; } + @Inject + public void setAnnotationResolver(@NotNull AnnotationResolver annotationResolver) { + this.annotationResolver = annotationResolver; + } + private void resolveBehaviorDeclarationBodies(@NotNull BodiesResolveContext bodiesResolveContext) { // Initialize context context = bodiesResolveContext; @@ -320,6 +327,12 @@ public class BodyResolver { } private void resolveClassAnnotations() { + for (Map.Entry entry : context.getClasses().entrySet()) { + resolveAnnotationArguments(entry.getValue().getScopeForSupertypeResolution(), entry.getKey()); + } + for (Map.Entry entry : context.getObjects().entrySet()) { + resolveAnnotationArguments(entry.getValue().getScopeForSupertypeResolution(), entry.getKey()); + } } private void resolveAnonymousInitializers() { @@ -367,7 +380,8 @@ public class BodyResolver { parameterScope.addVariableDescriptor(valueParameterDescriptor); } parameterScope.changeLockLevel(WritableScope.LockLevel.READING); - checkDefaultParameterValues(klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(), parameterScope); + resolveValueParameter(klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(), + parameterScope); } } } @@ -402,6 +416,8 @@ public class BodyResolver { resolvePropertyDelegate(property, propertyDescriptor, delegateExpression, classDescriptor.getScopeForMemberResolution(), propertyScope); } + resolveAnnotationArguments(propertyScope, property); + resolvePropertyAccessors(property, propertyDescriptor); processed.add(property); } @@ -429,6 +445,8 @@ public class BodyResolver { resolvePropertyDelegate(property, propertyDescriptor, delegateExpression, propertyScope, propertyScope); } + resolveAnnotationArguments(propertyScope, property); + resolvePropertyAccessors(property, propertyDescriptor); } } @@ -446,6 +464,7 @@ public class BodyResolver { PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter(); if (getter != null && getterDescriptor != null) { JetScope accessorScope = makeScopeForPropertyAccessor(getter, propertyDescriptor); + resolveAnnotationArguments(accessorScope, getter); resolveFunctionBody(fieldAccessTrackingTrace, getter, getterDescriptor, accessorScope); } @@ -453,6 +472,7 @@ public class BodyResolver { PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter(); if (setter != null && setterDescriptor != null) { JetScope accessorScope = makeScopeForPropertyAccessor(setter, propertyDescriptor); + resolveAnnotationArguments(accessorScope, setter); resolveFunctionBody(fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope); } } @@ -621,6 +641,7 @@ public class BodyResolver { JetScope declaringScope = this.context.getDeclaringScopes().apply(declaration); assert declaringScope != null; + resolveAnnotationArguments(declaringScope, declaration); resolveFunctionBody(trace, declaration, descriptor, declaringScope); assert descriptor.getReturnType() != null; @@ -643,24 +664,43 @@ public class BodyResolver { List valueParameters = function.getValueParameters(); List valueParameterDescriptors = functionDescriptor.getValueParameters(); - checkDefaultParameterValues(valueParameters, valueParameterDescriptors, functionInnerScope); + resolveValueParameter(valueParameters, valueParameterDescriptors, functionInnerScope); assert functionDescriptor.getReturnType() != null; } - private void checkDefaultParameterValues(List valueParameters, List valueParameterDescriptors, JetScope declaringScope) { + private void resolveValueParameter( + @NotNull List valueParameters, + @NotNull List valueParameterDescriptors, + @NotNull JetScope declaringScope + ) { for (int i = 0; i < valueParameters.size(); i++) { ValueParameterDescriptor valueParameterDescriptor = valueParameterDescriptors.get(i); - if (valueParameterDescriptor.hasDefaultValue()) { - JetParameter jetParameter = valueParameters.get(i); - JetExpression defaultValue = jetParameter.getDefaultValue(); - if (defaultValue != null) { - expressionTypingServices.getType(declaringScope, defaultValue, valueParameterDescriptor.getType(), DataFlowInfo.EMPTY, trace); - } + JetParameter jetParameter = valueParameters.get(i); + + resolveAnnotationArguments(declaringScope, jetParameter); + + resolveDefaultValue(declaringScope, valueParameterDescriptor, jetParameter); + } + } + + private void resolveDefaultValue( + @NotNull JetScope declaringScope, + @NotNull ValueParameterDescriptor valueParameterDescriptor, + @NotNull JetParameter jetParameter + ) { + if (valueParameterDescriptor.hasDefaultValue()) { + JetExpression defaultValue = jetParameter.getDefaultValue(); + if (defaultValue != null) { + expressionTypingServices.getType(declaringScope, defaultValue, valueParameterDescriptor.getType(), DataFlowInfo.EMPTY, trace); } } } + private void resolveAnnotationArguments(@NotNull JetScope scope, @NotNull JetModifierListOwner owner) { + annotationResolver.resolveAnnotationsArguments(scope, owner.getModifierList(), trace); + } + private static void computeDeferredType(JetType type) { // handle type inference loop: function or property body contains a reference to itself // fun f() = { f() } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java index e850543571f..b9c9f9fec90 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java @@ -125,7 +125,7 @@ public class DeclarationResolver { private void resolveAnnotationsForClassOrObject(AnnotationResolver annotationResolver, JetClassOrObject jetClass, MutableClassDescriptor descriptor) { JetModifierList modifierList = jetClass.getModifierList(); if (modifierList != null) { - descriptor.getAnnotations().addAll(annotationResolver.resolveAnnotations(descriptor.getScopeForSupertypeResolution(), modifierList.getAnnotationEntries(), trace)); + descriptor.getAnnotations().addAll(annotationResolver.resolveAnnotations(descriptor.getScopeForSupertypeResolution(), modifierList, trace)); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 24094762ab5..869cfdf69f4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -245,16 +245,39 @@ public class DescriptorResolver { } } + @NotNull + public SimpleFunctionDescriptor resolveFunctionDescriptorWithAnnotationArguments( + @NotNull DeclarationDescriptor containingDescriptor, + @NotNull JetScope scope, + @NotNull JetNamedFunction function, + @NotNull BindingTrace trace + ) { + return resolveFunctionDescriptor(containingDescriptor, scope, function, trace, + annotationResolver.resolveAnnotationsWithArguments(scope, function.getModifierList(), trace)); + } + @NotNull public SimpleFunctionDescriptor resolveFunctionDescriptor( + @NotNull DeclarationDescriptor containingDescriptor, + @NotNull JetScope scope, + @NotNull JetNamedFunction function, + @NotNull BindingTrace trace + ) { + return resolveFunctionDescriptor(containingDescriptor, scope, function, trace, + annotationResolver.resolveAnnotations(scope, function.getModifierList(), trace)); + } + + @NotNull + private SimpleFunctionDescriptor resolveFunctionDescriptor( @NotNull DeclarationDescriptor containingDescriptor, @NotNull final JetScope scope, @NotNull final JetNamedFunction function, - @NotNull final BindingTrace trace + @NotNull final BindingTrace trace, + @NotNull List annotations ) { final SimpleFunctionDescriptorImpl functionDescriptor = new SimpleFunctionDescriptorImpl( containingDescriptor, - annotationResolver.resolveAnnotations(scope, function.getModifierList(), trace), + annotations, JetPsiUtil.safeName(function.getName()), CallableMemberDescriptor.Kind.DECLARATION ); @@ -475,6 +498,26 @@ public class DescriptorResolver { public MutableValueParameterDescriptor resolveValueParameterDescriptor( JetScope scope, DeclarationDescriptor declarationDescriptor, JetParameter valueParameter, int index, JetType type, BindingTrace trace + ) { + return resolveValueParameterDescriptor(declarationDescriptor, valueParameter, index, type, trace, + annotationResolver.resolveAnnotations(scope, valueParameter.getModifierList(), trace)); + } + + @NotNull + public MutableValueParameterDescriptor resolveValueParameterDescriptorWithAnnotationArguments( + JetScope scope, DeclarationDescriptor declarationDescriptor, + JetParameter valueParameter, int index, JetType type, BindingTrace trace + ) { + return resolveValueParameterDescriptor(declarationDescriptor, valueParameter, index, type, trace, + annotationResolver.resolveAnnotationsWithArguments(scope, valueParameter.getModifierList(), + trace)); + } + + @NotNull + private MutableValueParameterDescriptor resolveValueParameterDescriptor( + DeclarationDescriptor declarationDescriptor, + JetParameter valueParameter, int index, JetType type, BindingTrace trace, + List annotations ) { JetType varargElementType = null; JetType variableType = type; @@ -485,7 +528,7 @@ public class DescriptorResolver { MutableValueParameterDescriptor valueParameterDescriptor = new ValueParameterDescriptorImpl( declarationDescriptor, index, - annotationResolver.resolveAnnotations(scope, valueParameter.getModifierList(), trace), + annotations, JetPsiUtil.safeName(valueParameter.getName()), variableType, valueParameter.getDefaultValue() != null, @@ -683,7 +726,7 @@ public class DescriptorResolver { BindingTrace trace ) { JetType type = resolveParameterType(scope, parameter, trace); - return resolveLocalVariableDescriptor(containingDeclaration, parameter, type, trace); + return resolveLocalVariableDescriptor(containingDeclaration, parameter, type, trace, scope); } private JetType resolveParameterType(JetScope scope, JetParameter parameter, BindingTrace trace) { @@ -706,11 +749,12 @@ public class DescriptorResolver { @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetParameter parameter, @NotNull JetType type, - BindingTrace trace + BindingTrace trace, + @NotNull JetScope scope ) { VariableDescriptor variableDescriptor = new LocalVariableDescriptor( containingDeclaration, - annotationResolver.getResolvedAnnotations(parameter.getModifierList(), trace), + annotationResolver.resolveAnnotationsWithArguments(scope, parameter.getModifierList(), trace), JetPsiUtil.safeName(parameter.getName()), type, false); @@ -729,7 +773,7 @@ public class DescriptorResolver { if (JetPsiUtil.isScriptDeclaration(variable)) { PropertyDescriptorImpl propertyDescriptor = new PropertyDescriptorImpl( containingDeclaration, - annotationResolver.getResolvedAnnotations(variable.getModifierList(), trace), + annotationResolver.resolveAnnotationsWithArguments(scope, variable.getModifierList(), trace), Modality.FINAL, Visibilities.INTERNAL, variable.isVar(), @@ -747,7 +791,7 @@ public class DescriptorResolver { } else { VariableDescriptorImpl variableDescriptor = - resolveLocalVariableDescriptorWithType(containingDeclaration, variable, null, trace); + resolveLocalVariableDescriptorWithType(scope, containingDeclaration, variable, null, trace); JetType type = getVariableType(variableDescriptor, scope, variable, dataFlowInfo, false, trace); // For a local variable the type must not be deferred @@ -758,6 +802,7 @@ public class DescriptorResolver { @NotNull public VariableDescriptorImpl resolveLocalVariableDescriptorWithType( + @NotNull JetScope scope, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetVariableDeclaration variable, @Nullable JetType type, @@ -765,7 +810,7 @@ public class DescriptorResolver { ) { VariableDescriptorImpl variableDescriptor = new LocalVariableDescriptor( containingDeclaration, - annotationResolver.getResolvedAnnotations(variable.getModifierList(), trace), + annotationResolver.resolveAnnotationsWithArguments(scope, variable.getModifierList(), trace), JetPsiUtil.safeName(variable.getName()), type, variable.isVar()); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java index e21c835d90a..3c0ebadd97a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java @@ -151,7 +151,7 @@ public abstract class AbstractLazyMemberScope declarations = declarationProvider.getFunctionDeclarations(name); for (JetNamedFunction functionDeclaration : declarations) { JetScope resolutionScope = getScopeForMemberDeclarationResolution(functionDeclaration); - result.add(resolveSession.getInjector().getDescriptorResolver().resolveFunctionDescriptor(thisDescriptor, resolutionScope, + result.add(resolveSession.getInjector().getDescriptorResolver().resolveFunctionDescriptorWithAnnotationArguments(thisDescriptor, resolutionScope, functionDeclaration, resolveSession.getTrace())); } @@ -179,9 +179,12 @@ public abstract class AbstractLazyMemberScope declarations = declarationProvider.getPropertyDeclarations(name); for (JetProperty propertyDeclaration : declarations) { JetScope resolutionScope = getScopeForMemberDeclarationResolution(propertyDeclaration); - result.add(resolveSession.getInjector().getDescriptorResolver().resolvePropertyDescriptor(thisDescriptor, resolutionScope, - propertyDeclaration, - resolveSession.getTrace())); + PropertyDescriptor propertyDescriptor = + resolveSession.getInjector().getDescriptorResolver().resolvePropertyDescriptor(thisDescriptor, resolutionScope, + propertyDeclaration, + resolveSession.getTrace()); + result.add(propertyDescriptor); + resolveSession.getInjector().getAnnotationResolver().resolveAnnotationsArguments(propertyDescriptor, resolveSession.getTrace(), resolutionScope); } // Objects are also properties diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java index 68c21d8ce92..4b85b50f89a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java @@ -231,7 +231,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { type = CANT_INFER_LAMBDA_PARAM_TYPE; } } - return context.expressionTypingServices.getDescriptorResolver().resolveValueParameterDescriptor( + return context.expressionTypingServices.getDescriptorResolver().resolveValueParameterDescriptorWithAnnotationArguments( context.scope, functionDescriptor, declaredParameter, index, type, context.trace); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index 235ad9ddf31..48fdfe7a872 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -331,7 +331,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { if (expectedParameterType == null) { expectedParameterType = ErrorUtils.createErrorType("Error"); } - variableDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope.getContainingDeclaration(), loopParameter, expectedParameterType, context.trace); + variableDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope.getContainingDeclaration(), loopParameter, expectedParameterType, context.trace, context.scope); } { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index bc28b281d37..554a9c58b9e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -423,7 +423,7 @@ public class ExpressionTypingUtils { componentType = ErrorUtils.createErrorType(componentName + "() return type"); } VariableDescriptor variableDescriptor = context.expressionTypingServices.getDescriptorResolver(). - resolveLocalVariableDescriptorWithType(writableScope.getContainingDeclaration(), entry, componentType, context.trace); + resolveLocalVariableDescriptorWithType(writableScope, writableScope.getContainingDeclaration(), entry, componentType, context.trace); VariableDescriptor olderVariable = writableScope.getLocalVariable(variableDescriptor.getName()); checkVariableShadowing(context, variableDescriptor, olderVariable); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java index 105c46f8ae6..db61f734c2e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java @@ -158,7 +158,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito @Override public JetTypeInfo visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) { SimpleFunctionDescriptor functionDescriptor = context.expressionTypingServices.getDescriptorResolver(). - resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function, context.trace); + resolveFunctionDescriptorWithAnnotationArguments(scope.getContainingDeclaration(), scope, function, context.trace); scope.addFunctionDescriptor(functionDescriptor); JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace); diff --git a/compiler/testData/resolveAnnotations/testFile.kt b/compiler/testData/resolveAnnotations/testFile.kt new file mode 100644 index 00000000000..c60671584c2 --- /dev/null +++ b/compiler/testData/resolveAnnotations/testFile.kt @@ -0,0 +1,39 @@ +package test + +ANNOTATION class MyClass { + ANNOTATION class object { + } + + ANNOTATION var prop: Int = 1 + [ANNOTATION] get + [ANNOTATION] set + ANNOTATION fun foo([ANNOTATION] param: Int) { + [ANNOTATION] class LocalClass { } + + [ANNOTATION] object LocalObject { } + + [ANNOTATION] fun localFun() {} + + [ANNOTATION] var localVar: Int = 1 + } + + ANNOTATION class InnerClass { + } + +} + +ANNOTATION object MyObject { +} + +ANNOTATION var topProp: Int = 1 + [ANNOTATION] get + [ANNOTATION] set + +ANNOTATION fun topFoo([ANNOTATION] param: Int) { +} + +val funLiteral = {([ANNOTATION] a: Int) -> a } + + +annotation class AnnString(a: String) +annotation class AnnInt(a: Int) \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/resolve/annotation/AnnotationDescriptorResolveTest.java b/compiler/tests/org/jetbrains/jet/resolve/annotation/AnnotationDescriptorResolveTest.java new file mode 100644 index 00000000000..27835190ae6 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/resolve/annotation/AnnotationDescriptorResolveTest.java @@ -0,0 +1,282 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.resolve.annotation; + + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.Function; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.JetLiteFixture; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.types.TypeProjection; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class AnnotationDescriptorResolveTest extends JetLiteFixture { + private static final String PATH = "compiler/testData/resolveAnnotations/testFile.kt"; + + private static final FqName NAMESPACE = new FqName("test"); + + private BindingContext context; + + @Override + protected JetCoreEnvironment createEnvironment() { + return JetTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations(getTestRootDisposable()); + } + + public void testIntAnnotation() throws IOException { + String content = getContent("AnnInt(1)"); + String expectedAnnotation = "AnnInt[a = 1.toInt()]"; + doTest(content, expectedAnnotation); + } + + public void testStringAnnotation() throws IOException { + String content = getContent("AnnString(\"test\")"); + String expectedAnnotation = "AnnString[a = \"test\"]"; + doTest(content, expectedAnnotation); + } + + private void doTest(@NotNull String content, @NotNull String expectedAnnotation) { + NamespaceDescriptor test = getNamespaceDescriptor(content); + ClassDescriptor myClass = getClassDescriptor(test, "MyClass"); + checkDescriptor(expectedAnnotation, myClass); + checkDescriptor(expectedAnnotation, getClassObjectDescriptor(myClass)); + checkDescriptor(expectedAnnotation, getInnerClassDescriptor(myClass, "InnerClass")); + + FunctionDescriptor foo = getFunctionDescriptor(myClass, "foo"); + checkDescriptor(expectedAnnotation, foo); + checkDescriptor(expectedAnnotation, getFunctionParameterDescriptor(foo, "param")); + + checkDescriptor(expectedAnnotation, getLocalClassDescriptor("LocalClass")); + checkDescriptor(expectedAnnotation, getLocalObjectDescriptor("LocalObject")); + checkDescriptor(expectedAnnotation, getLocalFunDescriptor("localFun")); + checkDescriptor(expectedAnnotation, getLocalVarDescriptor("localVar")); + + SimpleFunctionDescriptor anonymousFun = getAnonymousFunDescriptor(); + if (anonymousFun instanceof AnonymousFunctionDescriptor) { + for (ValueParameterDescriptor descriptor : anonymousFun.getValueParameters()) { + checkDescriptor(expectedAnnotation, descriptor); + } + } + + PropertyDescriptor prop = getPropertyDescriptor(myClass, "prop"); + checkDescriptor(expectedAnnotation, prop); + checkDescriptor(expectedAnnotation, prop.getGetter()); + checkDescriptor(expectedAnnotation, prop.getSetter()); + + FunctionDescriptor topFoo = getFunctionDescriptor(test, "topFoo"); + checkDescriptor(expectedAnnotation, topFoo); + checkDescriptor(expectedAnnotation, getFunctionParameterDescriptor(topFoo, "param")); + + PropertyDescriptor topProp = getPropertyDescriptor(test, "topProp"); + checkDescriptor(expectedAnnotation, topProp); + checkDescriptor(expectedAnnotation, topProp.getGetter()); + checkDescriptor(expectedAnnotation, topProp.getSetter()); + + checkDescriptor(expectedAnnotation, getObjectDescriptor(test, "MyObject")); + } + + @NotNull + private static FunctionDescriptor getFunctionDescriptor(@NotNull NamespaceDescriptor namespaceDescriptor, @NotNull String name) { + Name functionName = Name.identifier(name); + JetScope memberScope = namespaceDescriptor.getMemberScope(); + Collection functions = memberScope.getFunctions(functionName); + assert functions.size() == 1 : "Failed to find function " + functionName + " in class" + "." + namespaceDescriptor.getName(); + return functions.iterator().next(); + } + + @NotNull + private static FunctionDescriptor getFunctionDescriptor(@NotNull ClassDescriptor classDescriptor, @NotNull String name) { + Name functionName = Name.identifier(name); + JetScope memberScope = classDescriptor.getMemberScope(Collections.emptyList()); + Collection functions = memberScope.getFunctions(functionName); + assert functions.size() == 1 : "Failed to find function " + functionName + " in class" + "." + classDescriptor.getName(); + return functions.iterator().next(); + } + + @NotNull + private static PropertyDescriptor getPropertyDescriptor(@NotNull NamespaceDescriptor namespaceDescriptor, @NotNull String name) { + Name propertyName = Name.identifier(name); + JetScope memberScope = namespaceDescriptor.getMemberScope(); + Collection properties = memberScope.getProperties(propertyName); + assert properties.size() == 1 : "Failed to find property " + propertyName + " in class " + namespaceDescriptor.getName(); + return (PropertyDescriptor) properties.iterator().next(); + } + + @NotNull + private static PropertyDescriptor getPropertyDescriptor(@NotNull ClassDescriptor classDescriptor, @NotNull String name) { + Name propertyName = Name.identifier(name); + JetScope memberScope = classDescriptor.getMemberScope(Collections.emptyList()); + Collection properties = memberScope.getProperties(propertyName); + assert properties.size() == 1 : "Failed to find property " + propertyName + " in class " + classDescriptor.getName(); + return (PropertyDescriptor) properties.iterator().next(); + } + + @NotNull + private static ClassDescriptor getClassDescriptor(@NotNull NamespaceDescriptor namespaceDescriptor, @NotNull String name) { + Name className = Name.identifier(name); + ClassifierDescriptor aClass = namespaceDescriptor.getMemberScope().getClassifier(className); + assertNotNull("Failed to find class: " + namespaceDescriptor.getName() + "." + className, aClass); + assert aClass instanceof ClassDescriptor; + return (ClassDescriptor) aClass; + } + + @NotNull + private static ClassDescriptor getObjectDescriptor(@NotNull NamespaceDescriptor namespaceDescriptor, @NotNull String name) { + Name className = Name.identifier(name); + ClassDescriptor aClass = namespaceDescriptor.getMemberScope().getObjectDescriptor(className); + assertNotNull("Failed to find class: " + namespaceDescriptor.getName() + "." + className, aClass); + return aClass; + } + + @NotNull + private static ClassDescriptor getClassObjectDescriptor(@NotNull ClassDescriptor classDescriptor) { + ClassDescriptor objectDescriptor = classDescriptor.getClassObjectDescriptor(); + assert objectDescriptor != null : "Cannot find class object for class " + classDescriptor.getName(); + return objectDescriptor; + } + + @NotNull + private static ClassDescriptor getInnerClassDescriptor(@NotNull ClassDescriptor classDescriptor, @NotNull String name) { + Name propertyName = Name.identifier(name); + JetScope memberScope = classDescriptor.getMemberScope(Collections.emptyList()); + ClassifierDescriptor innerClass = memberScope.getClassifier(propertyName); + assert innerClass instanceof ClassDescriptor : "Failed to find inner class " + + propertyName + + " in class " + + classDescriptor.getName(); + return (ClassDescriptor) innerClass; + } + + @NotNull + private ClassDescriptor getLocalClassDescriptor(@NotNull String name) { + for (ClassDescriptor descriptor : context.getSliceContents(BindingContext.CLASS).values()) { + if (descriptor.getName().asString().equals(name)) { + return descriptor; + } + } + + fail("Failed to find local class " + name); + return null; + } + + @NotNull + private ClassDescriptor getLocalObjectDescriptor(@NotNull String name) { + for (ClassDescriptor descriptor : context.getSliceContents(BindingContext.OBJECT_DECLARATION_CLASS).values()) { + if (descriptor.getName().asString().equals(name)) { + return descriptor; + } + } + + fail("Failed to find local object " + name); + return null; + } + + @NotNull + private SimpleFunctionDescriptor getLocalFunDescriptor(@NotNull String name) { + for (SimpleFunctionDescriptor descriptor : context.getSliceContents(BindingContext.FUNCTION).values()) { + if (descriptor.getName().asString().equals(name)) { + return descriptor; + } + } + + fail("Failed to find local fun " + name); + return null; + } + + @NotNull + private VariableDescriptor getLocalVarDescriptor(@NotNull String name) { + for (VariableDescriptor descriptor : context.getSliceContents(BindingContext.VARIABLE).values()) { + if (descriptor.getName().asString().equals(name)) { + return descriptor; + } + } + + fail("Failed to find local variable " + name); + return null; + } + + @NotNull + private SimpleFunctionDescriptor getAnonymousFunDescriptor() { + for (SimpleFunctionDescriptor descriptor : context.getSliceContents(BindingContext.FUNCTION).values()) { + if (descriptor instanceof AnonymousFunctionDescriptor) { + return descriptor; + } + } + + fail("Failed to find anonymous fun"); + return null; + } + + private static ValueParameterDescriptor findValueParameter(List parameters, String name) { + for (ValueParameterDescriptor parameter : parameters) { + if (parameter.getName().asString().equals(name)) { + return parameter; + } + } + return null; + } + + @NotNull + private static ValueParameterDescriptor getFunctionParameterDescriptor( + @NotNull FunctionDescriptor functionDescriptor, + @NotNull String name + ) { + ValueParameterDescriptor parameter = findValueParameter(functionDescriptor.getValueParameters(), name); + assertNotNull("Cannot find function parameter with name " + name, parameter); + return parameter; + } + + @NotNull + private NamespaceDescriptor getNamespaceDescriptor(@NotNull String content) { + JetFile ktFile = JetTestUtils.createFile("dummy.kt", content, getProject()); + context = JetTestUtils.analyzeFile(ktFile).getBindingContext(); + + NamespaceDescriptor namespaceDescriptor = context.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, NAMESPACE); + assertNotNull("Failed to find namespace: " + NAMESPACE, namespaceDescriptor); + return namespaceDescriptor; + } + + private static String getContent(@NotNull String annotationText) throws IOException { + File file = new File(PATH); + String content = JetTestUtils.doLoadFile(file).replaceAll("ANNOTATION", annotationText); + return content; + } + + private static void checkDescriptor(String expectedAnnotation, DeclarationDescriptor member) { + String actual = StringUtil.join(member.getAnnotations(), new Function() { + @Override + public String fun(AnnotationDescriptor annotationDescriptor) { + return annotationDescriptor.toString(); + } + }, " "); + assertEquals("Failed to resolve annotation descriptor for " + member.toString(), expectedAnnotation, actual); + } +} diff --git a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java index 14976718021..0b4037bb055 100644 --- a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java +++ b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java @@ -130,6 +130,7 @@ public class InjectorForTopDownAnalyzerForJs { this.topDownAnalysisContext.setTopDownAnalysisParameters(topDownAnalysisParameters); + this.bodyResolver.setAnnotationResolver(annotationResolver); this.bodyResolver.setCallResolver(callResolver); this.bodyResolver.setContext(topDownAnalysisContext); this.bodyResolver.setControlFlowAnalyzer(controlFlowAnalyzer);