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 c6a01fa1f6a..f6cd2fa8782 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -36,6 +36,7 @@ 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.TypeResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CandidateResolver; @@ -86,6 +87,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly private CallResolver callResolver; private ArgumentTypeResolver argumentTypeResolver; private ExpressionTypingServices expressionTypingServices; + private CallExpressionResolver callExpressionResolver; private TypeResolver typeResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; private CandidateResolver candidateResolver; @@ -137,6 +139,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.callResolver = new CallResolver(); this.argumentTypeResolver = new ArgumentTypeResolver(); this.expressionTypingServices = new ExpressionTypingServices(); + this.callExpressionResolver = new CallExpressionResolver(); this.typeResolver = new TypeResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.candidateResolver = new CandidateResolver(); @@ -228,11 +231,14 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly argumentTypeResolver.setExpressionTypingServices(expressionTypingServices); argumentTypeResolver.setTypeResolver(typeResolver); + expressionTypingServices.setCallExpressionResolver(callExpressionResolver); expressionTypingServices.setCallResolver(callResolver); expressionTypingServices.setDescriptorResolver(descriptorResolver); expressionTypingServices.setProject(project); expressionTypingServices.setTypeResolver(typeResolver); + callExpressionResolver.setExpressionTypingServices(expressionTypingServices); + typeResolver.setAnnotationResolver(annotationResolver); typeResolver.setDescriptorResolver(descriptorResolver); typeResolver.setModuleConfiguration(moduleConfiguration); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java index f173a5820eb..22ed27a7737 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java @@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.ModuleConfiguration; 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; @@ -49,6 +50,7 @@ public class InjectorForBodyResolve { private CallResolver callResolver; private ArgumentTypeResolver argumentTypeResolver; private ExpressionTypingServices expressionTypingServices; + private CallExpressionResolver callExpressionResolver; private DescriptorResolver descriptorResolver; private AnnotationResolver annotationResolver; private TypeResolver typeResolver; @@ -75,6 +77,7 @@ public class InjectorForBodyResolve { 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(); @@ -103,11 +106,14 @@ public class InjectorForBodyResolve { argumentTypeResolver.setExpressionTypingServices(expressionTypingServices); argumentTypeResolver.setTypeResolver(typeResolver); + expressionTypingServices.setCallExpressionResolver(callExpressionResolver); expressionTypingServices.setCallResolver(callResolver); expressionTypingServices.setDescriptorResolver(descriptorResolver); expressionTypingServices.setProject(project); expressionTypingServices.setTypeResolver(typeResolver); + callExpressionResolver.setExpressionTypingServices(expressionTypingServices); + descriptorResolver.setAnnotationResolver(annotationResolver); descriptorResolver.setExpressionTypingServices(expressionTypingServices); descriptorResolver.setTypeResolver(typeResolver); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java index 6cdb2ff029a..2d8e2d11dfe 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java @@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.resolve.lazy.ScopeProvider; import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.psi.JetImportsFactory; +import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver; import org.jetbrains.jet.lang.resolve.calls.CandidateResolver; @@ -47,6 +48,7 @@ public class InjectorForLazyResolve { private AnnotationResolver annotationResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; private JetImportsFactory jetImportsFactory; + private CallExpressionResolver callExpressionResolver; private CallResolver callResolver; private ArgumentTypeResolver argumentTypeResolver; private CandidateResolver candidateResolver; @@ -68,6 +70,7 @@ public class InjectorForLazyResolve { this.annotationResolver = new AnnotationResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.jetImportsFactory = new JetImportsFactory(); + this.callExpressionResolver = new CallExpressionResolver(); this.callResolver = new CallResolver(); this.argumentTypeResolver = new ArgumentTypeResolver(); this.candidateResolver = new CandidateResolver(); @@ -76,6 +79,7 @@ public class InjectorForLazyResolve { this.descriptorResolver.setExpressionTypingServices(expressionTypingServices); this.descriptorResolver.setTypeResolver(typeResolver); + this.expressionTypingServices.setCallExpressionResolver(callExpressionResolver); this.expressionTypingServices.setCallResolver(callResolver); this.expressionTypingServices.setDescriptorResolver(descriptorResolver); this.expressionTypingServices.setProject(project); @@ -91,6 +95,8 @@ public class InjectorForLazyResolve { this.jetImportsFactory.setProject(project); + callExpressionResolver.setExpressionTypingServices(expressionTypingServices); + callResolver.setArgumentTypeResolver(argumentTypeResolver); callResolver.setCandidateResolver(candidateResolver); callResolver.setExpressionTypingServices(expressionTypingServices); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java index caa9a6e703d..9f626f5d6e9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.di; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import com.intellij.openapi.project.Project; import org.jetbrains.jet.lang.ModuleConfiguration; +import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver; import org.jetbrains.jet.lang.resolve.TypeResolver; @@ -35,6 +36,7 @@ public class InjectorForMacros { private ExpressionTypingServices expressionTypingServices; private final Project project; private final ModuleConfiguration moduleConfiguration; + private CallExpressionResolver callExpressionResolver; private CallResolver callResolver; private ArgumentTypeResolver argumentTypeResolver; private TypeResolver typeResolver; @@ -50,6 +52,7 @@ public class InjectorForMacros { this.expressionTypingServices = new ExpressionTypingServices(); this.project = project; this.moduleConfiguration = moduleConfiguration; + this.callExpressionResolver = new CallExpressionResolver(); this.callResolver = new CallResolver(); this.argumentTypeResolver = new ArgumentTypeResolver(); this.typeResolver = new TypeResolver(); @@ -58,11 +61,14 @@ public class InjectorForMacros { this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.candidateResolver = new CandidateResolver(); + this.expressionTypingServices.setCallExpressionResolver(callExpressionResolver); this.expressionTypingServices.setCallResolver(callResolver); this.expressionTypingServices.setDescriptorResolver(descriptorResolver); this.expressionTypingServices.setProject(project); this.expressionTypingServices.setTypeResolver(typeResolver); + callExpressionResolver.setExpressionTypingServices(expressionTypingServices); + callResolver.setArgumentTypeResolver(argumentTypeResolver); callResolver.setCandidateResolver(candidateResolver); callResolver.setExpressionTypingServices(expressionTypingServices); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java index 183b852e318..d9ca97de24e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java @@ -34,6 +34,7 @@ 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.TypeResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CandidateResolver; @@ -68,6 +69,7 @@ public class InjectorForTopDownAnalyzerBasic { private CallResolver callResolver; private ArgumentTypeResolver argumentTypeResolver; private ExpressionTypingServices expressionTypingServices; + private CallExpressionResolver callExpressionResolver; private TypeResolver typeResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; private CandidateResolver candidateResolver; @@ -104,6 +106,7 @@ public class InjectorForTopDownAnalyzerBasic { this.callResolver = new CallResolver(); this.argumentTypeResolver = new ArgumentTypeResolver(); this.expressionTypingServices = new ExpressionTypingServices(); + this.callExpressionResolver = new CallExpressionResolver(); this.typeResolver = new TypeResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.candidateResolver = new CandidateResolver(); @@ -169,11 +172,14 @@ public class InjectorForTopDownAnalyzerBasic { argumentTypeResolver.setExpressionTypingServices(expressionTypingServices); argumentTypeResolver.setTypeResolver(typeResolver); + expressionTypingServices.setCallExpressionResolver(callExpressionResolver); expressionTypingServices.setCallResolver(callResolver); expressionTypingServices.setDescriptorResolver(descriptorResolver); expressionTypingServices.setProject(project); expressionTypingServices.setTypeResolver(typeResolver); + callExpressionResolver.setExpressionTypingServices(expressionTypingServices); + typeResolver.setAnnotationResolver(annotationResolver); typeResolver.setDescriptorResolver(descriptorResolver); typeResolver.setModuleConfiguration(moduleConfiguration); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index 56b703c6ff0..c6655d355bc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -22,36 +22,45 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; +import org.jetbrains.jet.lang.resolve.constants.ConstantUtils; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.ChainedScope; import org.jetbrains.jet.lang.resolve.scopes.FilteringScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; -import org.jetbrains.jet.lang.types.ErrorUtils; -import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.JetTypeInfo; -import org.jetbrains.jet.lang.types.NamespaceType; +import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.expressions.DataFlowUtils; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext; +import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.lexer.JetTokens; +import javax.inject.Inject; import java.util.Collections; import static org.jetbrains.jet.lang.diagnostics.Errors.*; -import static org.jetbrains.jet.lang.resolve.BindingContext.NON_DEFAULT_EXPRESSION_DATA_FLOW; -import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; -import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLUTION_SCOPE; +import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; public class CallExpressionResolver { + @NotNull + private ExpressionTypingServices expressionTypingServices; + + @Inject + public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) { + this.expressionTypingServices = expressionTypingServices; + } + @Nullable - private static JetType lookupNamespaceOrClassObject(@NotNull JetSimpleNameExpression expression, @NotNull ExpressionTypingContext context) { + private JetType lookupNamespaceOrClassObject(@NotNull JetSimpleNameExpression expression, @NotNull ExpressionTypingContext context) { Name referencedName = expression.getReferencedNameAsName(); ClassifierDescriptor classifier = context.scope.getClassifier(referencedName); if (classifier != null) { @@ -97,7 +106,7 @@ public class CallExpressionResolver { } @NotNull - private static JetScope getStaticNestedClassesScope(@NotNull ClassDescriptor descriptor) { + private JetScope getStaticNestedClassesScope(@NotNull ClassDescriptor descriptor) { JetScope innerClassesScope = descriptor.getUnsubstitutedInnerClassesScope(); return new FilteringScope(innerClassesScope, new Predicate() { @Override @@ -107,7 +116,7 @@ public class CallExpressionResolver { }); } - private static boolean furtherNameLookup( + private boolean furtherNameLookup( @NotNull JetSimpleNameExpression expression, @NotNull JetType[] result, @NotNull ExpressionTypingContext context @@ -126,7 +135,7 @@ public class CallExpressionResolver { } @Nullable - private static NamespaceType lookupNamespaceType(@NotNull JetSimpleNameExpression expression, @NotNull ExpressionTypingContext context) { + private NamespaceType lookupNamespaceType(@NotNull JetSimpleNameExpression expression, @NotNull ExpressionTypingContext context) { Name name = expression.getReferencedNameAsName(); NamespaceDescriptor namespace = context.scope.getNamespace(name); if (namespace == null) { @@ -134,7 +143,7 @@ public class CallExpressionResolver { } context.trace.record(REFERENCE_TARGET, expression, namespace); - // Construct a NamespaceType with everything from the namespace and with static nested classes of the corresponding class (if any) + // Construct a NamespaceType with everything from the namespace and with nested classes of the corresponding class (if any) JetScope scope; ClassifierDescriptor classifier = context.scope.getClassifier(name); if (classifier instanceof ClassDescriptor) { @@ -147,7 +156,7 @@ public class CallExpressionResolver { } @Nullable - private static ResolvedCall getResolvedCallForFunction( + private ResolvedCall getResolvedCallForFunction( @NotNull Call call, @NotNull JetExpression callExpression, @NotNull ReceiverValue receiver, @NotNull ExpressionTypingContext context, @NotNull boolean[] result ) { @@ -166,7 +175,7 @@ public class CallExpressionResolver { } @Nullable - private static JetType getVariableType(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver, + private JetType getVariableType(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver, @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context, @NotNull boolean[] result) { TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create( @@ -201,7 +210,7 @@ public class CallExpressionResolver { } @NotNull - public static JetTypeInfo getSimpleNameExpressionTypeInfo(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver, + public JetTypeInfo getSimpleNameExpressionTypeInfo(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver, @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context) { boolean[] result = new boolean[1]; @@ -230,13 +239,14 @@ public class CallExpressionResolver { } @NotNull - public static JetTypeInfo getCallExpressionTypeInfo(@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver, + public JetTypeInfo getCallExpressionTypeInfo(@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver, @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context) { boolean[] result = new boolean[1]; Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression); - TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function call", callExpression); + TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function call", + callExpression); ResolvedCall resolvedCall = getResolvedCallForFunction(call, callExpression, receiver, context.replaceBindingTrace(traceForFunction), result); if (result[0]) { @@ -272,7 +282,7 @@ public class CallExpressionResolver { return JetTypeInfo.create(null, context.dataFlowInfo); } - private static void checkSuper(@NotNull ReceiverValue receiverValue, @NotNull OverloadResolutionResults results, + private void checkSuper(@NotNull ReceiverValue receiverValue, @NotNull OverloadResolutionResults results, @NotNull BindingTrace trace, @NotNull JetExpression expression) { if (!results.isSingleResult()) return; if (!(receiverValue instanceof ExpressionReceiver)) return; @@ -286,7 +296,7 @@ public class CallExpressionResolver { } @NotNull - public static JetTypeInfo getSelectorReturnTypeInfo( + public JetTypeInfo getSelectorReturnTypeInfo( @NotNull ReceiverValue receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @@ -314,4 +324,41 @@ public class CallExpressionResolver { } return JetTypeInfo.create(null, context.dataFlowInfo); } + + @NotNull + public JetTypeInfo getQualifiedExpressionTypeInfo(@NotNull JetQualifiedExpression expression, @NotNull ExpressionTypingContext context) { + // TODO : functions as values + JetExpression selectorExpression = expression.getSelectorExpression(); + JetExpression receiverExpression = expression.getReceiverExpression(); + JetTypeInfo receiverTypeInfo = expressionTypingServices.getTypeInfoWithNamespaces( + receiverExpression, context.scope, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace); + JetType receiverType = receiverTypeInfo.getType(); + if (selectorExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo); + if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText()); + + context = context.replaceDataFlowInfo(receiverTypeInfo.getDataFlowInfo()); + + if (selectorExpression instanceof JetSimpleNameExpression) { + ConstantUtils.propagateConstantValues(expression, context.trace, (JetSimpleNameExpression) selectorExpression); + } + + JetTypeInfo selectorReturnTypeInfo = getSelectorReturnTypeInfo( + new ExpressionReceiver(receiverExpression, receiverType), expression.getOperationTokenNode(), selectorExpression, context); + JetType selectorReturnType = selectorReturnTypeInfo.getType(); + + //TODO move further + if (!(receiverType instanceof NamespaceType) && expression.getOperationSign() == JetTokens.SAFE_ACCESS) { + if (selectorReturnType != null && !selectorReturnType.isNullable() && !KotlinBuiltIns.getInstance().isUnit(selectorReturnType)) { + if (receiverType.isNullable()) { + selectorReturnType = TypeUtils.makeNullable(selectorReturnType); + } + } + } + + // TODO : this is suspicious: remove this code? + if (selectorReturnType != null) { + context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, selectorReturnType); + } + return DataFlowUtils.checkType(selectorReturnType, expression, context, selectorReturnTypeInfo.getDataFlowInfo()); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.java new file mode 100644 index 00000000000..d65639bf492 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.java @@ -0,0 +1,66 @@ +/* + * 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.lang.resolve.constants; + +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetQualifiedExpression; +import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.types.expressions.OperatorConventions; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; + +import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*; +import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.BYTE; +import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.INT; + +public class ConstantUtils { + + public static void propagateConstantValues(JetQualifiedExpression expression, BindingTrace trace, JetSimpleNameExpression selectorExpression) { + JetExpression receiverExpression = expression.getReceiverExpression(); + CompileTimeConstant receiverValue = trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, receiverExpression); + CompileTimeConstant wholeExpressionValue = trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, expression); + DeclarationDescriptor declarationDescriptor = trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, selectorExpression); + if (wholeExpressionValue == null && receiverValue != null && !(receiverValue instanceof ErrorValue) && receiverValue.getValue() instanceof Number + && KotlinBuiltIns.getInstance().getNumber() == declarationDescriptor) { + Number value = (Number) receiverValue.getValue(); + Name referencedName = selectorExpression.getReferencedNameAsName(); + if (OperatorConventions.NUMBER_CONVERSIONS.contains(referencedName)) { + if (DOUBLE.equals(referencedName)) { + trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new DoubleValue(value.doubleValue())); + } + else if (FLOAT.equals(referencedName)) { + trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new FloatValue(value.floatValue())); + } + else if (LONG.equals(referencedName)) { + trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new LongValue(value.longValue())); + } + else if (SHORT.equals(referencedName)) { + trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new ShortValue(value.shortValue())); + } + else if (BYTE.equals(referencedName)) { + trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new ByteValue(value.byteValue())); + } + else if (INT.equals(referencedName)) { + trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new IntValue(value.intValue())); + } + } + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index b5ae90b5954..e4943f35551 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -69,7 +69,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { public JetTypeInfo visitSimpleNameExpression(JetSimpleNameExpression expression, ExpressionTypingContext context) { // TODO : other members // TODO : type substitutions??? - JetTypeInfo typeInfo = CallExpressionResolver.getSimpleNameExpressionTypeInfo(expression, NO_RECEIVER, null, context); + CallExpressionResolver callExpressionResolver = context.expressionTypingServices.getCallExpressionResolver(); + JetTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, NO_RECEIVER, null, context); JetType type = DataFlowUtils.checkType(typeInfo.getType(), expression, context); ExpressionTypingUtils.checkWrappingInRef(expression, context.trace, context.scope); return JetTypeInfo.create(type, typeInfo.getDataFlowInfo()); // TODO : Extensions to this @@ -589,76 +590,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { @Override public JetTypeInfo visitQualifiedExpression(JetQualifiedExpression expression, ExpressionTypingContext context) { - // TODO : functions as values - JetExpression selectorExpression = expression.getSelectorExpression(); - JetExpression receiverExpression = expression.getReceiverExpression(); - ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE); - JetTypeInfo receiverTypeInfo = facade.getTypeInfo(receiverExpression, contextWithNoExpectedType.replaceNamespacesAllowed(true)); - JetType receiverType = receiverTypeInfo.getType(); - if (selectorExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo); - if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText()); - - context = context.replaceDataFlowInfo(receiverTypeInfo.getDataFlowInfo()); - - if (selectorExpression instanceof JetSimpleNameExpression) { - propagateConstantValues(expression, context, (JetSimpleNameExpression) selectorExpression); - } - - JetTypeInfo selectorReturnTypeInfo = CallExpressionResolver.getSelectorReturnTypeInfo( - new ExpressionReceiver(receiverExpression, receiverType), expression.getOperationTokenNode(), selectorExpression, context); - JetType selectorReturnType = selectorReturnTypeInfo.getType(); - - //TODO move further - if (!(receiverType instanceof NamespaceType) && expression.getOperationSign() == JetTokens.SAFE_ACCESS) { - if (selectorReturnType != null && !selectorReturnType.isNullable() && !KotlinBuiltIns.getInstance().isUnit(selectorReturnType)) { - if (receiverType.isNullable()) { - selectorReturnType = TypeUtils.makeNullable(selectorReturnType); - } - } - } - - // TODO : this is suspicious: remove this code? - if (selectorReturnType != null) { - context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, selectorReturnType); - } - return DataFlowUtils.checkType(selectorReturnType, expression, context, selectorReturnTypeInfo.getDataFlowInfo()); - } - - private static void propagateConstantValues(JetQualifiedExpression expression, ExpressionTypingContext context, JetSimpleNameExpression selectorExpression) { - JetExpression receiverExpression = expression.getReceiverExpression(); - CompileTimeConstant receiverValue = context.trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, receiverExpression); - CompileTimeConstant wholeExpressionValue = context.trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, expression); - DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, selectorExpression); - if (wholeExpressionValue == null && receiverValue != null && !(receiverValue instanceof ErrorValue) && receiverValue.getValue() instanceof Number - && KotlinBuiltIns.getInstance().getNumber() == declarationDescriptor) { - Number value = (Number) receiverValue.getValue(); - Name referencedName = selectorExpression.getReferencedNameAsName(); - if (OperatorConventions.NUMBER_CONVERSIONS.contains(referencedName)) { - if (DOUBLE.equals(referencedName)) { - context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new DoubleValue(value.doubleValue())); - } - else if (FLOAT.equals(referencedName)) { - context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new FloatValue(value.floatValue())); - } - else if (LONG.equals(referencedName)) { - context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new LongValue(value.longValue())); - } - else if (SHORT.equals(referencedName)) { - context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new ShortValue(value.shortValue())); - } - else if (BYTE.equals(referencedName)) { - context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new ByteValue(value.byteValue())); - } - else if (INT.equals(referencedName)) { - context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new IntValue(value.intValue())); - } - } - } + CallExpressionResolver callExpressionResolver = context.expressionTypingServices.getCallExpressionResolver(); + return callExpressionResolver.getQualifiedExpressionTypeInfo(expression, context); } @Override public JetTypeInfo visitCallExpression(JetCallExpression expression, ExpressionTypingContext context) { - JetTypeInfo expressionTypeInfo = CallExpressionResolver.getCallExpressionTypeInfo(expression, NO_RECEIVER, null, context); + CallExpressionResolver callExpressionResolver = context.expressionTypingServices.getCallExpressionResolver(); + JetTypeInfo expressionTypeInfo = callExpressionResolver.getCallExpressionTypeInfo(expression, NO_RECEIVER, null, context); return DataFlowUtils.checkType(expressionTypeInfo.getType(), expression, context, expressionTypeInfo.getDataFlowInfo()); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java index 2923889c0a6..789866355b5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java @@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.descriptors.ScriptDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -61,6 +62,8 @@ public class ExpressionTypingServices { @NotNull private CallResolver callResolver; @NotNull + private CallExpressionResolver callExpressionResolver; + @NotNull private DescriptorResolver descriptorResolver; @NotNull private TypeResolver typeResolver; @@ -87,6 +90,16 @@ public class ExpressionTypingServices { this.callResolver = callResolver; } + @NotNull + public CallExpressionResolver getCallExpressionResolver() { + return callExpressionResolver; + } + + @Inject + public void setCallExpressionResolver(@NotNull CallExpressionResolver callExpressionResolver) { + this.callExpressionResolver = callExpressionResolver; + } + @NotNull public DescriptorResolver getDescriptorResolver() { return descriptorResolver; @@ -128,11 +141,10 @@ public class ExpressionTypingServices { return getTypeInfo(scope, expression, expectedType, dataFlowInfo, trace).getType(); } - public JetType getTypeWithNamespaces(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull BindingTrace trace) { + public JetTypeInfo getTypeInfoWithNamespaces(@NotNull JetExpression expression, @NotNull JetScope scope, @NotNull JetType expectedType, @NotNull DataFlowInfo dataFlowInfo, @NotNull BindingTrace trace) { ExpressionTypingContext context = ExpressionTypingContext.newContext( - this, trace, scope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, true); - return expressionTypingFacade.getTypeInfo(expression, context).getType(); -// return ((ExpressionTypingContext) ExpressionTyperVisitorWithNamespaces).INSTANCE.getType(expression, ExpressionTypingContext.newRootContext(semanticServices, trace, scope, DataFlowInfo.getEmpty(), TypeUtils.NO_EXPECTED_TYPE, TypeUtils.NO_EXPECTED_TYPE)); + this, trace, scope, dataFlowInfo, expectedType, true); + return expressionTypingFacade.getTypeInfo(expression, context); } @NotNull diff --git a/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java b/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java index 3d786069964..8c5fa25f383 100644 --- a/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java +++ b/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java @@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.ModuleConfiguration; import com.intellij.openapi.project.Project; import org.jetbrains.jet.lang.resolve.AnnotationResolver; +import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver; import org.jetbrains.jet.lang.resolve.calls.CandidateResolver; @@ -41,6 +42,7 @@ public class InjectorForTests { private ModuleConfiguration moduleConfiguration; private final Project project; private AnnotationResolver annotationResolver; + private CallExpressionResolver callExpressionResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; private ArgumentTypeResolver argumentTypeResolver; private CandidateResolver candidateResolver; @@ -56,6 +58,7 @@ public class InjectorForTests { this.moduleConfiguration = ModuleConfiguration.EMPTY; this.project = project; this.annotationResolver = new AnnotationResolver(); + this.callExpressionResolver = new CallExpressionResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.argumentTypeResolver = new ArgumentTypeResolver(); this.candidateResolver = new CandidateResolver(); @@ -64,6 +67,7 @@ public class InjectorForTests { this.descriptorResolver.setExpressionTypingServices(expressionTypingServices); this.descriptorResolver.setTypeResolver(typeResolver); + this.expressionTypingServices.setCallExpressionResolver(callExpressionResolver); this.expressionTypingServices.setCallResolver(callResolver); this.expressionTypingServices.setDescriptorResolver(descriptorResolver); this.expressionTypingServices.setProject(project); @@ -82,6 +86,8 @@ public class InjectorForTests { annotationResolver.setCallResolver(callResolver); annotationResolver.setExpressionTypingServices(expressionTypingServices); + callExpressionResolver.setExpressionTypingServices(expressionTypingServices); + argumentTypeResolver.setExpressionTypingServices(expressionTypingServices); argumentTypeResolver.setTypeResolver(typeResolver); 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 11193fe1503..f5f01bdce20 100644 --- a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java +++ b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java @@ -34,6 +34,7 @@ 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.TypeResolver; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CandidateResolver; @@ -68,6 +69,7 @@ public class InjectorForTopDownAnalyzerForJs { private CallResolver callResolver; private ArgumentTypeResolver argumentTypeResolver; private ExpressionTypingServices expressionTypingServices; + private CallExpressionResolver callExpressionResolver; private TypeResolver typeResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; private CandidateResolver candidateResolver; @@ -104,6 +106,7 @@ public class InjectorForTopDownAnalyzerForJs { this.callResolver = new CallResolver(); this.argumentTypeResolver = new ArgumentTypeResolver(); this.expressionTypingServices = new ExpressionTypingServices(); + this.callExpressionResolver = new CallExpressionResolver(); this.typeResolver = new TypeResolver(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.candidateResolver = new CandidateResolver(); @@ -169,11 +172,14 @@ public class InjectorForTopDownAnalyzerForJs { argumentTypeResolver.setExpressionTypingServices(expressionTypingServices); argumentTypeResolver.setTypeResolver(typeResolver); + expressionTypingServices.setCallExpressionResolver(callExpressionResolver); expressionTypingServices.setCallResolver(callResolver); expressionTypingServices.setDescriptorResolver(descriptorResolver); expressionTypingServices.setProject(project); expressionTypingServices.setTypeResolver(typeResolver); + callExpressionResolver.setExpressionTypingServices(expressionTypingServices); + typeResolver.setAnnotationResolver(annotationResolver); typeResolver.setDescriptorResolver(descriptorResolver); typeResolver.setModuleConfiguration(moduleConfiguration);