diff --git a/idea/src/org/jetbrains/jet/lang/ErrorHandlerWithRegions.java b/idea/src/org/jetbrains/jet/lang/ErrorHandlerWithRegions.java index 92b39db5a62..2455db0be78 100644 --- a/idea/src/org/jetbrains/jet/lang/ErrorHandlerWithRegions.java +++ b/idea/src/org/jetbrains/jet/lang/ErrorHandlerWithRegions.java @@ -66,6 +66,10 @@ public class ErrorHandlerWithRegions extends ErrorHandler { return new DiagnosticsRegion(currentWorker); } + public void close() { + assert workers.isEmpty() : "Open regions remain: " + workers; + } + private void setWorker() { worker = workers.isEmpty() ? parent : workers.peek(); } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java b/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java index d44493564a6..bac10421d8f 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java @@ -98,7 +98,7 @@ public class FunctionDescriptorUtil { @NotNull public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) { - WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, trace.getErrorHandler()); + WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, trace.getErrorHandler()).setDebugName("Function inner scope"); JetType receiverType = descriptor.getReceiverType(); if (receiverType != null) { parameterScope.setThisType(receiverType); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetArgument.java b/idea/src/org/jetbrains/jet/lang/psi/JetArgument.java index 5a637440998..88e6d5311c3 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetArgument.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetArgument.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lexer.JetTokens; @@ -8,7 +9,7 @@ import org.jetbrains.jet.lexer.JetTokens; /** * @author max */ -public class JetArgument extends JetElement { +public class JetArgument extends JetElement implements ValueArgumentPsi { public JetArgument(@NotNull ASTNode node) { super(node); } @@ -22,6 +23,11 @@ public class JetArgument extends JetElement { return findChildByClass(JetExpression.class); } + @Override + public PsiElement asElement() { + return this; + } + @Nullable public String getArgumentName() { ASTNode firstChildNode = getNode().getFirstChildNode(); diff --git a/idea/src/org/jetbrains/jet/lang/psi/ValueArgumentPsi.java b/idea/src/org/jetbrains/jet/lang/psi/ValueArgumentPsi.java new file mode 100644 index 00000000000..613431c6b09 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/psi/ValueArgumentPsi.java @@ -0,0 +1,48 @@ +package org.jetbrains.jet.lang.psi; + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.Nullable; + +/** + * @author abreslav + */ +public interface ValueArgumentPsi { + + class ArgumentExpressionWrapper implements ValueArgumentPsi { + + private final JetExpression expression; + + public ArgumentExpressionWrapper(JetExpression expression) { + this.expression = expression; + } + + @Override + public PsiElement asElement() { + return expression; + } + + @Override + public String getArgumentName() { + return null; + } + + @Override + public boolean isNamed() { + return false; + } + + @Override + public JetExpression getArgumentExpression() { + return expression; + } + } + + PsiElement asElement(); + @Nullable + String getArgumentName(); + + boolean isNamed(); + + @Nullable + public JetExpression getArgumentExpression(); +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java b/idea/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java index f70838fcbf8..5247f8e9150 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -71,7 +71,7 @@ public class AnalyzingUtils { JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope(); ModuleDescriptor owner = new ModuleDescriptor(""); - final WritableScope scope = new WritableScopeImpl(libraryScope, owner, bindingTraceContext.getErrorHandler()); + final WritableScope scope = new WritableScopeImpl(libraryScope, owner, bindingTraceContext.getErrorHandler()).setDebugName("Root scope in analyzeNamespace"); // scope.importScope(javaSemanticServices.getDescriptorResolver().resolveNamespace("").getMemberScope()); // scope.importScope(javaSemanticServices.getDescriptorResolver().resolveNamespace("java.lang").getMemberScope()); scope.importScope(new JavaPackageScope("", null, javaSemanticServices)); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java index 7be00a6645e..13daaf37c58 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java @@ -33,8 +33,6 @@ public interface BindingTrace { void removeStatementRecord(@NotNull JetElement statement); - void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression); - void requireBackingField(@NotNull PropertyDescriptor propertyDescriptor); void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java index 35975fe30d9..57357d72412 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java @@ -52,10 +52,6 @@ public class BindingTraceAdapter implements BindingTrace { originalTrace.recordBlock(expression); } - public void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression) { - originalTrace.removeReferenceResolution(referenceExpression); - } - @Override public void recordStatement(@NotNull JetElement statement) { originalTrace.recordStatement(statement); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java index d43d65b0b90..1faf1be7c15 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java @@ -28,17 +28,56 @@ public class BindingTraceContext implements BindingContext, BindingTrace { private final Map constructorDeclarationsToDescriptors = new HashMap(); private final Map namespaceDeclarationsToDescriptors = Maps.newHashMap(); private final Map primaryConstructorParameterDeclarationsToPropertyDescriptors = Maps.newHashMap(); + private final Map autoCasts = Maps.newHashMap(); + private final Map resolutionScopes = Maps.newHashMap(); + private final Set blocks = new HashSet(); private final Set statements = new HashSet(); private final Set backingFieldRequired = new HashSet(); private final Set processed = Sets.newHashSet(); - private final Map autoCasts = Maps.newHashMap(); private final List diagnostics = Lists.newArrayList(); - private final ErrorHandlerWithRegions errorHandler = new ErrorHandlerWithRegions(new CollectingErrorHandler(diagnostics)); - private Map resolutionScopes = Maps.newHashMap(); -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + private final ErrorHandlerWithRegions errorHandler = new ErrorHandlerWithRegions(new CollectingErrorHandler(diagnostics)); + + public BindingTraceContext() { + } + + public void destructiveMerge(BindingTraceContext other) { + safePutAll(expressionTypes, other.expressionTypes); + resolutionResults.putAll(other.resolutionResults); + safePutAll(labelResolutionResults, other.labelResolutionResults); + safePutAll(types, other.types); + safePutAll(descriptorToDeclarations, other.descriptorToDeclarations); + safePutAll(declarationsToDescriptors, other.declarationsToDescriptors); + safePutAll(constructorDeclarationsToDescriptors, other.constructorDeclarationsToDescriptors); + safePutAll(namespaceDeclarationsToDescriptors, other.namespaceDeclarationsToDescriptors); + safePutAll(primaryConstructorParameterDeclarationsToPropertyDescriptors, other.primaryConstructorParameterDeclarationsToPropertyDescriptors); + safePutAll(autoCasts, other.autoCasts); + safePutAll(resolutionScopes, other.resolutionScopes); + + blocks.addAll(other.blocks); + statements.addAll(other.statements); + backingFieldRequired.addAll(other.backingFieldRequired); + processed.addAll(other.processed); + + diagnostics.addAll(other.diagnostics); + } + + private void safePutAll(Map my, Map other) { + assert keySetIntersection(my, other).isEmpty() : keySetIntersection(my, other); + + my.putAll(other); + } + + private HashSet keySetIntersection(Map my, Map other) { + HashSet keySet = Sets.newHashSet(my.keySet()); + keySet.retainAll(other.keySet()); + return keySet; + } + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @NotNull public ErrorHandlerWithRegions getErrorHandler() { @@ -60,11 +99,6 @@ public class BindingTraceContext implements BindingContext, BindingTrace { safePut(labelResolutionResults, expression, element); } - @Override - public void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression) { - resolutionResults.remove(referenceExpression); - } - @Override public void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type) { safePut(types, typeReference, type); @@ -101,8 +135,7 @@ public class BindingTraceContext implements BindingContext, BindingTrace { private void safePut(Map map, K key, V value) { V oldValue = map.put(key, value); - // TODO: - assert oldValue == null || oldValue == value : key + ": " + oldValue + " and " + value; + assert oldValue == null || oldValue == value : (key instanceof PsiElement ? key.toString() + " \"" + ((PsiElement) key).getText() + "\"" : key.toString()) + " -> " + oldValue + " and " + value; } @Override @@ -127,7 +160,7 @@ public class BindingTraceContext implements BindingContext, BindingTrace { @Override public void recordResolutionScope(@NotNull JetExpression expression, @NotNull JetScope scope) { - resolutionScopes.put(expression, scope); + safePut(resolutionScopes, expression, scope); } @Override diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 15c8cfcc013..41e0369bc09 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -164,7 +164,7 @@ public class ClassDescriptorResolver { AnnotationResolver.INSTANCE.resolveAnnotations(function.getModifierList()), JetPsiUtil.safeName(function.getName()) ); - WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, trace.getErrorHandler()); + WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, trace.getErrorHandler()).setDebugName("Function descriptor header scope"); innerScope.addLabeledDeclaration(functionDescriptor); List typeParameterDescriptors = resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters()); @@ -474,7 +474,7 @@ public class ClassDescriptorResolver { typeParameterDescriptors = Collections.emptyList(); } else { - WritableScope writableScope = new WritableScopeImpl(scope, containingDeclaration, trace.getErrorHandler()); + WritableScope writableScope = new WritableScopeImpl(scope, containingDeclaration, trace.getErrorHandler()).setDebugName("Scope with type parameters of a property"); typeParameterDescriptors = resolveTypeParameters(containingDeclaration, writableScope, typeParameters); resolveGenericBounds(property, writableScope, typeParameterDescriptors); scopeWithTypeParameters = writableScope; @@ -525,7 +525,7 @@ public class ClassDescriptorResolver { LazyValue lazyValue = new LazyValue() { @Override protected JetType compute() { - return semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.THROW_EXCEPTION).safeGetType(scope, initializer, false, null); // TODO + return semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.THROW_EXCEPTION).safeGetType(scope, initializer, false, JetTypeInferrer.NO_EXPECTED_TYPE); } }; if (allowDeferred) { @@ -646,7 +646,7 @@ public class ClassDescriptorResolver { typeParameters, resolveValueParameters( constructorDescriptor, - new WritableScopeImpl(scope, classDescriptor, trace.getErrorHandler()), + new WritableScopeImpl(scope, classDescriptor, trace.getErrorHandler()).setDebugName("Scope with value parameters of a constructor"), valueParameters)); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 4de1da8dc51..8d179ca681c 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -128,6 +128,8 @@ public class TopDownAnalyzer { resolveFunctionAndPropertyHeaders(); // Constructor headers are resolved as well resolveBehaviorDeclarationBodies(); + + trace.getErrorHandler().close(); } private void collectNamespacesAndClassifiers( @@ -150,7 +152,7 @@ public class TopDownAnalyzer { Collections.emptyList(), // TODO name ); - namespaceDescriptor.initialize(new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, trace.getErrorHandler())); + namespaceDescriptor.initialize(new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, trace.getErrorHandler()).setDebugName("Namespace member scope")); owner.addNamespace(namespaceDescriptor); trace.recordDeclarationResolution(namespace, namespaceDescriptor); } @@ -570,7 +572,7 @@ public class TopDownAnalyzer { JetExpression delegateExpression = specifier.getDelegateExpression(); if (delegateExpression != null) { JetScope scope = scopeForConstructor == null ? descriptor.getScopeForMemberResolution() : scopeForConstructor; - JetType type = typeInferrer.getType(scope, delegateExpression, false, null); + JetType type = typeInferrer.getType(scope, delegateExpression, false, JetTypeInferrer.NO_EXPECTED_TYPE); JetType supertype = trace.getBindingContext().resolveTypeReference(specifier.getTypeReference()); if (type != null && !semanticServices.getTypeChecker().isSubtypeOf(type, supertype)) { // TODO : Convertible? trace.getErrorHandler().typeMismatch(delegateExpression, supertype, type); @@ -583,7 +585,7 @@ public class TopDownAnalyzer { JetTypeReference typeReference = call.getTypeReference(); if (typeReference != null) { if (descriptor.getUnsubstitutedPrimaryConstructor() != null) { - typeInferrer.checkConstructorCall(scopeForConstructor, typeReference, call); + typeInferrer.checkTypeInitializerCall(scopeForConstructor, typeReference, call); } else { JetArgumentList valueArgumentList = call.getValueArgumentList(); @@ -642,7 +644,7 @@ public class TopDownAnalyzer { final JetScope scopeForConstructor = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution(), true); JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow for (JetClassInitializer anonymousInitializer : anonymousInitializers) { - typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), true, null); + typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), true, JetTypeInferrer.NO_EXPECTED_TYPE); } } else { @@ -684,7 +686,7 @@ public class TopDownAnalyzer { public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { JetTypeReference typeReference = call.getTypeReference(); if (typeReference != null) { - typeInferrerForInitializers.checkConstructorCall(functionInnerScope, typeReference, call); + typeInferrerForInitializers.checkTypeInitializerCall(functionInnerScope, typeReference, call); } } @@ -734,7 +736,7 @@ public class TopDownAnalyzer { @NotNull private JetScope getInnerScopeForConstructor(@NotNull ConstructorDescriptor descriptor, @NotNull JetScope declaringScope, boolean primary) { - WritableScope constructorScope = new WritableScopeImpl(declaringScope, declaringScope.getContainingDeclaration(), trace.getErrorHandler()); + WritableScope constructorScope = new WritableScopeImpl(declaringScope, declaringScope.getContainingDeclaration(), trace.getErrorHandler()).setDebugName("Inner scope for constructor"); for (PropertyDescriptor propertyDescriptor : ((MutableClassDescriptor) descriptor.getContainingDeclaration()).getProperties()) { constructorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor); } @@ -802,7 +804,7 @@ public class TopDownAnalyzer { } private JetScope getPropertyDeclarationInnerScope(@NotNull JetScope outerScope, @NotNull PropertyDescriptor propertyDescriptor) { - WritableScopeImpl result = new WritableScopeImpl(outerScope, propertyDescriptor, trace.getErrorHandler()); + WritableScopeImpl result = new WritableScopeImpl(outerScope, propertyDescriptor, trace.getErrorHandler()).setDebugName("Property declaration inner scope"); for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParemeters()) { result.addTypeParameterDescriptor(typeParameterDescriptor); } @@ -816,7 +818,7 @@ public class TopDownAnalyzer { private void resolvePropertyAccessors(JetProperty property, PropertyDescriptor propertyDescriptor, JetScope declaringScope) { BindingTraceAdapter fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor); - WritableScope accessorScope = new WritableScopeImpl(getPropertyDeclarationInnerScope(declaringScope, propertyDescriptor), declaringScope.getContainingDeclaration(), trace.getErrorHandler()); + WritableScope accessorScope = new WritableScopeImpl(getPropertyDeclarationInnerScope(declaringScope, propertyDescriptor), declaringScope.getContainingDeclaration(), trace.getErrorHandler()).setDebugName("Accessor scope"); accessorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor); JetPropertyAccessor getter = property.getGetter(); @@ -858,7 +860,7 @@ public class TopDownAnalyzer { private void resolvePropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, JetExpression initializer, JetScope scope) { JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(property, initializer); // TODO : flow JET-15 JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider); - JetType type = typeInferrer.getType(getPropertyDeclarationInnerScope(scope, propertyDescriptor), initializer, false, null); + JetType type = typeInferrer.getType(getPropertyDeclarationInnerScope(scope, propertyDescriptor), initializer, false, JetTypeInferrer.NO_EXPECTED_TYPE); JetType expectedType; PropertySetterDescriptor setter = propertyDescriptor.getSetter(); @@ -908,4 +910,6 @@ public class TopDownAnalyzer { assert functionDescriptor.getUnsubstitutedReturnType() != null; } + + } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/WritableScopeImpl.java b/idea/src/org/jetbrains/jet/lang/resolve/WritableScopeImpl.java index 637e6d84d19..71e514080f6 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/WritableScopeImpl.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/WritableScopeImpl.java @@ -326,4 +326,10 @@ public class WritableScopeImpl extends WritableScopeWithImports { public boolean hasDeclaredItems() { return variableClassOrNamespaceDescriptors != null && !variableClassOrNamespaceDescriptors.isEmpty(); } + + @Override + public WritableScopeImpl setDebugName(@NotNull String debugName) { + super.setDebugName(debugName); + return this; + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/WritableScopeWithImports.java b/idea/src/org/jetbrains/jet/lang/resolve/WritableScopeWithImports.java index 9316b0e3d85..8fdb9473559 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/WritableScopeWithImports.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/WritableScopeWithImports.java @@ -96,7 +96,7 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement public void importClassifierAlias(@NotNull String importedClassifierName, @NotNull ClassifierDescriptor classifierDescriptor) { if (currentIndividualImportScope == null) { - WritableScopeImpl writableScope = new WritableScopeImpl(JetScope.EMPTY, getContainingDeclaration(), ErrorHandler.DO_NOTHING); + WritableScopeImpl writableScope = new WritableScopeImpl(JetScope.EMPTY, getContainingDeclaration(), ErrorHandler.DO_NOTHING).setDebugName("Individual import scope"); importScope(writableScope); currentIndividualImportScope = writableScope; } @@ -105,7 +105,7 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement @Override public String toString() { - return debugName + " for " + getContainingDeclaration(); + return getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)) + " " + debugName + " for " + getContainingDeclaration(); } } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java index 89d981b1f3a..2e253f17e58 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java @@ -185,7 +185,7 @@ public class JetStandardClasses { /*package*/ static final JetScope STANDARD_CLASSES; static { - WritableScope writableScope = new WritableScopeImpl(JetScope.EMPTY, STANDARD_CLASSES_NAMESPACE, ErrorHandler.DO_NOTHING); + WritableScope writableScope = new WritableScopeImpl(JetScope.EMPTY, STANDARD_CLASSES_NAMESPACE, ErrorHandler.DO_NOTHING).setDebugName("JetStandardClasses.STANDARD_CLASSES"); STANDARD_CLASSES = writableScope; writableScope.addClassifierAlias("Unit", getTuple(0)); diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java index b6382721b88..3522837d3e6 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java @@ -75,7 +75,7 @@ public class JetStandardLibrary { JetSemanticServices bootstrappingSemanticServices = JetSemanticServices.createSemanticServices(this); BindingTraceContext bindingTraceContext = new BindingTraceContext(); TopDownAnalyzer bootstrappingTDA = new TopDownAnalyzer(bootstrappingSemanticServices, bindingTraceContext); - WritableScopeImpl writableScope = new WritableScopeImpl(JetStandardClasses.STANDARD_CLASSES, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, ErrorHandler.THROW_EXCEPTION); + WritableScopeImpl writableScope = new WritableScopeImpl(JetStandardClasses.STANDARD_CLASSES, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, ErrorHandler.THROW_EXCEPTION).setDebugName("Root bootstrap scope"); // this.libraryScope = bootstrappingTDA.process(JetStandardClasses.STANDARD_CLASSES, file.getRootNamespace().getDeclarations()); // bootstrappingTDA.process(writableScope, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, file.getRootNamespace().getDeclarations()); bootstrappingTDA.processStandardLibraryNamespace(writableScope, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, file.getRootNamespace()); diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeImpl.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeImpl.java index b0f7f47fb12..efa2cc99fbe 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeImpl.java @@ -44,11 +44,13 @@ public final class JetTypeImpl extends AnnotatedImpl implements JetType { classDescriptor.getMemberScope(Collections.emptyList())); } + @NotNull @Override public TypeConstructor getConstructor() { return constructor; } + @NotNull @Override public List getArguments() { return arguments; diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 384e1c455a1..83dffca2bef 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -55,47 +55,73 @@ public class JetTypeInferrer { throw new UnsupportedOperationException(); // TODO } }; + public static final JetType NO_EXPECTED_TYPE = new JetType() { + @NotNull + @Override + public TypeConstructor getConstructor() { + throw new UnsupportedOperationException(); // TODO + } - private static final Map unaryOperationNames = ImmutableMap.builder() + @NotNull + @Override + public List getArguments() { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public boolean isNullable() { + throw new UnsupportedOperationException(); // TODO + } + + @NotNull + @Override + public JetScope getMemberScope() { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public List getAnnotations() { + throw new UnsupportedOperationException(); // TODO + } + }; + + private static final ImmutableMap unaryOperationNames = ImmutableMap.builder() .put(JetTokens.PLUSPLUS, "inc") .put(JetTokens.MINUSMINUS, "dec") .put(JetTokens.PLUS, "plus") .put(JetTokens.MINUS, "minus") .put(JetTokens.EXCL, "not") .build(); - private static final Map binaryOperationNames = new HashMap(); + private static final ImmutableMap binaryOperationNames = ImmutableMap.builder() + .put(JetTokens.MUL, "times") + .put(JetTokens.PLUS, "plus") + .put(JetTokens.MINUS, "minus") + .put(JetTokens.DIV, "div") + .put(JetTokens.PERC, "mod") + .put(JetTokens.ARROW, "arrow") + .put(JetTokens.RANGE, "rangeTo") + .build(); - static { - binaryOperationNames.put(JetTokens.MUL, "times"); - binaryOperationNames.put(JetTokens.PLUS, "plus"); - binaryOperationNames.put(JetTokens.MINUS, "minus"); - binaryOperationNames.put(JetTokens.DIV, "div"); - binaryOperationNames.put(JetTokens.PERC, "mod"); - binaryOperationNames.put(JetTokens.ARROW, "arrow"); - binaryOperationNames.put(JetTokens.RANGE, "rangeTo"); - } - private static final Set comparisonOperations = new HashSet(Arrays.asList(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ)); - private static final Set equalsOperations = new HashSet(Arrays.asList(JetTokens.EQEQ, JetTokens.EXCLEQ)); + private static final Set comparisonOperations = Sets.newHashSet(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ); + private static final Set equalsOperations = Sets.newHashSet(JetTokens.EQEQ, JetTokens.EXCLEQ); - private static final Set inOperations = new HashSet(Arrays.asList(JetTokens.IN_KEYWORD, JetTokens.NOT_IN)); - public static final Map assignmentOperationNames = new HashMap(); + private static final Set inOperations = Sets.newHashSet(JetTokens.IN_KEYWORD, JetTokens.NOT_IN); + public static final ImmutableMap assignmentOperationNames = ImmutableMap.builder() + .put(JetTokens.MULTEQ, "timesAssign") + .put(JetTokens.DIVEQ, "divAssign") + .put(JetTokens.PERCEQ, "modAssign") + .put(JetTokens.PLUSEQ, "plusAssign") + .put(JetTokens.MINUSEQ, "minusAssign") + .build(); - static { - assignmentOperationNames.put(JetTokens.MULTEQ, "timesAssign"); - assignmentOperationNames.put(JetTokens.DIVEQ, "divAssign"); - assignmentOperationNames.put(JetTokens.PERCEQ, "modAssign"); - assignmentOperationNames.put(JetTokens.PLUSEQ, "plusAssign"); - assignmentOperationNames.put(JetTokens.MINUSEQ, "minusAssign"); - } - private static final Map assignmentOperationCounterparts = new HashMap(); + private static final ImmutableMap assignmentOperationCounterparts = ImmutableMap.builder() + .put(JetTokens.MULTEQ, JetTokens.MUL) + .put(JetTokens.DIVEQ, JetTokens.DIV) + .put(JetTokens.PERCEQ, JetTokens.PERC) + .put(JetTokens.PLUSEQ, JetTokens.PLUS) + .put(JetTokens.MINUSEQ, JetTokens.MINUS) + .build(); - static { - assignmentOperationCounterparts.put(JetTokens.MULTEQ, JetTokens.MUL); - assignmentOperationCounterparts.put(JetTokens.DIVEQ, JetTokens.DIV); - assignmentOperationCounterparts.put(JetTokens.PERCEQ, JetTokens.PERC); - assignmentOperationCounterparts.put(JetTokens.PLUSEQ, JetTokens.PLUS); - assignmentOperationCounterparts.put(JetTokens.MINUSEQ, JetTokens.MINUS); - } private final BindingTrace trace; private final JetSemanticServices semanticServices; private final TypeResolver typeResolver; @@ -113,7 +139,7 @@ public class JetTypeInferrer { } @NotNull - public JetType safeGetType(@NotNull final JetScope scope, @NotNull JetExpression expression, boolean preferBlock, @Nullable JetType expectedType) { + public JetType safeGetType(@NotNull final JetScope scope, @NotNull JetExpression expression, boolean preferBlock, @NotNull JetType expectedType) { JetType type = getType(scope, expression, preferBlock, expectedType); if (type != null) { return type; @@ -122,12 +148,12 @@ public class JetTypeInferrer { } @Nullable - public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, boolean preferBlock, @Nullable JetType expectedType) { + public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, boolean preferBlock, @NotNull JetType expectedType) { return new TypeInferrerVisitor(scope, preferBlock, DataFlowInfo.getEmpty(), expectedType, FORBIDDEN).getType(expression); } public JetType getTypeWithNamespaces(@NotNull final JetScope scope, @NotNull JetExpression expression, boolean preferBlock) { - return new TypeInferrerVisitorWithNamespaces(scope, preferBlock, DataFlowInfo.getEmpty(), null, null).getType(expression); + return new TypeInferrerVisitorWithNamespaces(scope, preferBlock, DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, null).getType(expression); } @Nullable @@ -346,7 +372,7 @@ public class JetTypeInferrer { public void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, @Nullable final JetType expectedReturnType) { JetExpression bodyExpression = function.getBodyExpression(); assert bodyExpression != null; - new TypeInferrerVisitor(functionInnerScope, function.hasBlockBody(), DataFlowInfo.getEmpty(), null, expectedReturnType).getType(bodyExpression); + new TypeInferrerVisitor(functionInnerScope, function.hasBlockBody(), DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, expectedReturnType).getType(bodyExpression); List unreachableElements = Lists.newArrayList(); flowInformationProvider.collectUnreachableExpressions(function.asElement(), unreachableElements); @@ -409,7 +435,7 @@ public class JetTypeInferrer { JetExpression bodyExpression = function.getBodyExpression(); assert bodyExpression != null; JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace); - new TypeInferrerVisitor(functionInnerScope, function.hasBlockBody(), DataFlowInfo.getEmpty(), null, FORBIDDEN).getType(bodyExpression); + new TypeInferrerVisitor(functionInnerScope, function.hasBlockBody(), DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, FORBIDDEN).getType(bodyExpression); Collection returnedExpressions = new ArrayList(); Collection elementsReturningUnit = new ArrayList(); flowInformationProvider.collectReturnedInformation(function.asElement(), returnedExpressions, elementsReturningUnit); @@ -434,7 +460,7 @@ public class JetTypeInferrer { } DeclarationDescriptor containingDescriptor = outerScope.getContainingDeclaration(); - WritableScope scope = new WritableScopeImpl(outerScope, containingDescriptor, trace.getErrorHandler()); + WritableScope scope = new WritableScopeImpl(outerScope, containingDescriptor, trace.getErrorHandler()).setDebugName("getBlockReturnedType"); return getBlockReturnedTypeWithWritableScope(scope, block, dataFlowInfo, extectedReturnType); } @@ -443,7 +469,7 @@ public class JetTypeInferrer { return JetStandardClasses.getUnitType(); } - TypeInferrerVisitorWithWritableScope blockLevelVisitor = new TypeInferrerVisitorWithWritableScope(scope, true, dataFlowInfo, null, extectedReturnType); + TypeInferrerVisitorWithWritableScope blockLevelVisitor = new TypeInferrerVisitorWithWritableScope(scope, true, dataFlowInfo, NO_EXPECTED_TYPE, extectedReturnType); JetType result = null; for (JetElement statement : block) { @@ -459,7 +485,7 @@ public class JetTypeInferrer { // newScope = scope; // } if (newDataFlowInfo != dataFlowInfo) {// || newScope != scope) { - blockLevelVisitor = new TypeInferrerVisitorWithWritableScope(scope, true, newDataFlowInfo, null, extectedReturnType); + blockLevelVisitor = new TypeInferrerVisitorWithWritableScope(scope, true, newDataFlowInfo, NO_EXPECTED_TYPE, extectedReturnType); } else { blockLevelVisitor.resetResult(); // TODO : maybe it's better to recreate the visitors with the same scope? @@ -530,7 +556,7 @@ public class JetTypeInferrer { List valueArgumentTypes = new ArrayList(); for (JetExpression valueArgument : positionedValueArguments) { - valueArgumentTypes.add(safeGetType(scope, valueArgument, false, null)); // TODO + valueArgumentTypes.add(safeGetType(scope, valueArgument, false, NO_EXPECTED_TYPE)); // TODO } OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, valueArgumentTypes); @@ -564,7 +590,7 @@ public class JetTypeInferrer { } @Nullable - public JetType checkConstructorCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCall call) { + public JetType checkTypeInitializerCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCall call) { JetTypeElement typeElement = typeReference.getTypeElement(); if (typeElement instanceof JetUserType) { JetUserType userType = (JetUserType) typeElement; @@ -677,6 +703,9 @@ public class JetTypeInferrer { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private class TypeInferrerVisitor extends JetVisitor { + +// protected final BindingTrace trace; + protected final JetScope scope; private final boolean preferBlock; protected final DataFlowInfo dataFlowInfo; @@ -684,17 +713,16 @@ public class JetTypeInferrer { protected JetType result; protected DataFlowInfo resultDataFlowInfo; - protected final JetType extectedType; - protected final JetType extectedReturnType; + protected final JetType expectedType; + protected final JetType expectedReturnType; -// protected WritableScope resultScope; - private TypeInferrerVisitor(@NotNull JetScope scope, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo, @Nullable JetType expectedType, @Nullable JetType expectedReturnType) { + private TypeInferrerVisitor(@NotNull JetScope scope, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo, @NotNull JetType expectedType, @Nullable JetType expectedReturnType) { this.scope = scope; this.preferBlock = preferBlock; this.dataFlowInfo = dataFlowInfo; - this.extectedType = expectedType; - this.extectedReturnType = expectedReturnType; + this.expectedType = expectedType; + this.expectedReturnType = expectedReturnType; } @Nullable @@ -702,29 +730,19 @@ public class JetTypeInferrer { return resultDataFlowInfo; } -// public WritableScope getResultScope() { -// if (resultScope instanceof WritableScopeImpl) { -// WritableScopeImpl writableScope = (WritableScopeImpl) resultScope; -// if (!writableScope.hasDeclaredItems()) { -// return null; -// } -// } -// return resultScope; -// } -// @Nullable public JetType getType(@NotNull JetScope scope, @NotNull JetExpression expression, boolean preferBlock) { - return getType(scope, expression, preferBlock, dataFlowInfo); + return getTypeWithNewDataFlowInfo(scope, expression, preferBlock, dataFlowInfo); } @Nullable - public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo) { + public JetType getTypeWithNewDataFlowInfo(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo) { TypeInferrerVisitor visitor; if (this.scope == scope && this.preferBlock == preferBlock && result == null && dataFlowInfo == this.dataFlowInfo) { visitor = this; } else { - visitor = createNew(scope, preferBlock, dataFlowInfo, extectedType, extectedReturnType); + visitor = createNew(scope, preferBlock, dataFlowInfo, expectedType, expectedReturnType); } JetType type = visitor.getType(expression); visitor.result = null; @@ -732,14 +750,13 @@ public class JetTypeInferrer { } @NotNull - public TypeInferrerVisitor createNew(@NotNull JetScope scope, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo, @Nullable JetType expectedType, @Nullable JetType expectedReturnType) { + public TypeInferrerVisitor createNew(@NotNull JetScope scope, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo, @NotNull JetType expectedType, @Nullable JetType expectedReturnType) { return new TypeInferrerVisitor(scope, preferBlock, dataFlowInfo, expectedType, expectedReturnType); } @Nullable public final JetType getType(@NotNull JetExpression expression) { assert result == null; - trace.recordResolutionScope(expression, scope); if (trace.isProcessed(expression)) { return trace.getBindingContext().getExpressionType(expression); } @@ -765,6 +782,9 @@ public class JetTypeInferrer { result = null; } + if (!trace.isProcessed(expression)) { + trace.recordResolutionScope(expression, scope); + } trace.markAsProcessed(expression); return result; } @@ -890,7 +910,7 @@ public class JetTypeInferrer { public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) { if (preferBlock && !expression.hasParameterSpecification()) { trace.recordBlock(expression); - result = getBlockReturnedType(scope, expression.getBody(), dataFlowInfo, extectedReturnType); + result = getBlockReturnedType(scope, expression.getBody(), dataFlowInfo, expectedReturnType); return; } @@ -934,12 +954,12 @@ public class JetTypeInferrer { if (returnTypeRef != null) { returnType = typeResolver.resolveType(scope, returnTypeRef); } else { - WritableScope writableScope = new WritableScopeImpl(scope, functionDescriptor, trace.getErrorHandler()); + WritableScope writableScope = new WritableScopeImpl(scope, functionDescriptor, trace.getErrorHandler()).setDebugName("Inner scope of a function literal"); for (VariableDescriptor variableDescriptor : valueParameterDescriptors) { writableScope.addVariableDescriptor(variableDescriptor); } writableScope.setThisType(receiverType); - returnType = getBlockReturnedType(writableScope, expression.getBody(), dataFlowInfo, extectedReturnType); + returnType = getBlockReturnedType(writableScope, expression.getBody(), dataFlowInfo, expectedReturnType); } JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("") : returnType; functionDescriptor.setReturnType(safeReturnType); @@ -1016,7 +1036,7 @@ public class JetTypeInferrer { @Override public void visitReturnExpression(JetReturnExpression expression) { - if (extectedReturnType == FORBIDDEN) { + if (expectedReturnType == FORBIDDEN) { trace.getErrorHandler().genericError(expression.getNode(), "'return' is not allowed here"); return; } @@ -1027,14 +1047,14 @@ public class JetTypeInferrer { returnedType = getType(scope, returnedExpression, false); } else { - if (extectedReturnType != null && !JetStandardClasses.isUnit(extectedReturnType)) { - trace.getErrorHandler().genericError(expression.getNode(), "This function must return a value of type " + extectedReturnType); + if (expectedReturnType != null && !JetStandardClasses.isUnit(expectedReturnType)) { + trace.getErrorHandler().genericError(expression.getNode(), "This function must return a value of type " + expectedReturnType); } } - if (extectedReturnType != null && returnedType != null) { - if (!semanticServices.getTypeChecker().isSubtypeOf(returnedType, extectedReturnType)) { - trace.getErrorHandler().typeMismatch(returnedExpression == null ? expression : returnedExpression, extectedReturnType, returnedType); + if (expectedReturnType != null && returnedType != null) { + if (!semanticServices.getTypeChecker().isSubtypeOf(returnedType, expectedReturnType)) { + trace.getErrorHandler().typeMismatch(returnedExpression == null ? expression : returnedExpression, expectedReturnType, returnedType); } } @@ -1053,7 +1073,7 @@ public class JetTypeInferrer { @Override public void visitTypeofExpression(JetTypeofExpression expression) { - JetType type = safeGetType(scope, expression.getBaseExpression(), false, null); // TODO + JetType type = safeGetType(scope, expression.getBaseExpression(), false, NO_EXPECTED_TYPE); // TODO result = semanticServices.getStandardLibrary().getTypeInfoType(type); } @@ -1109,7 +1129,7 @@ public class JetTypeInferrer { List entries = expression.getEntries(); List types = new ArrayList(); for (JetExpression entry : entries) { - types.add(safeGetType(scope, entry, false, null)); // TODO + types.add(safeGetType(scope, entry, false, NO_EXPECTED_TYPE)); // TODO } // TODO : labels result = JetStandardClasses.getTupleType(types); @@ -1217,7 +1237,7 @@ public class JetTypeInferrer { @Override public void visitBlockExpression(JetBlockExpression expression) { - result = getBlockReturnedType(scope, expression.getStatements(), dataFlowInfo, extectedReturnType); + result = getBlockReturnedType(scope, expression.getStatements(), dataFlowInfo, expectedReturnType); } @Override @@ -1225,7 +1245,7 @@ public class JetTypeInferrer { // TODO :change scope according to the bound value in the when header final JetExpression subjectExpression = expression.getSubjectExpression(); - final JetType subjectType = subjectExpression != null ? safeGetType(scope, subjectExpression, false, null) : ErrorUtils.createErrorType("Unknown type"); + final JetType subjectType = subjectExpression != null ? safeGetType(scope, subjectExpression, false, NO_EXPECTED_TYPE) : ErrorUtils.createErrorType("Unknown type"); final VariableDescriptor variableDescriptor = subjectExpression != null ? getVariableDescriptorFromSimpleName(subjectExpression) : null; // TODO : exhaustive patterns @@ -1233,7 +1253,7 @@ public class JetTypeInferrer { Set expressionTypes = Sets.newHashSet(); for (JetWhenEntry whenEntry : expression.getEntries()) { JetWhenCondition condition = whenEntry.getCondition(); - WritableScope scopeToExtend = newWritableScopeImpl(); + WritableScope scopeToExtend = newWritableScopeImpl().setDebugName("Scope extended in when entry"); DataFlowInfo newDataFlowInfo = dataFlowInfo; if (condition != null) { newDataFlowInfo = checkWhenCondition(subjectExpression, subjectType, condition, scopeToExtend, variableDescriptor); @@ -1241,7 +1261,7 @@ public class JetTypeInferrer { JetWhenExpression subWhen = whenEntry.getSubWhen(); JetExpression bodyExpression = subWhen == null ? whenEntry.getExpression() : subWhen; if (bodyExpression != null) { - JetType type = getType(scopeToExtend, bodyExpression, true, newDataFlowInfo); + JetType type = getTypeWithNewDataFlowInfo(scopeToExtend, bodyExpression, true, newDataFlowInfo); if (type != null) { expressionTypes.add(type); } @@ -1419,7 +1439,7 @@ public class JetTypeInferrer { if (catchParameter != null) { VariableDescriptor variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, catchParameter); if (catchBody != null) { - WritableScope catchScope = newWritableScopeImpl(); + WritableScope catchScope = newWritableScopeImpl().setDebugName("Catch scope"); catchScope.addVariableDescriptor(variableDescriptor); JetType type = getType(catchScope, catchBody, true); if (type != null) { @@ -1455,13 +1475,13 @@ public class JetTypeInferrer { JetExpression elseBranch = expression.getElse(); JetExpression thenBranch = expression.getThen(); - WritableScopeImpl thenScope = newWritableScopeImpl(); + WritableScopeImpl thenScope = newWritableScopeImpl().setDebugName("Then scope"); DataFlowInfo thenInfo = extractDataFlowInfoFromCondition(condition, true, thenScope); DataFlowInfo elseInfo = extractDataFlowInfoFromCondition(condition, false, null); if (elseBranch == null) { if (thenBranch != null) { - JetType type = getType(thenScope, thenBranch, true, thenInfo); + JetType type = getTypeWithNewDataFlowInfo(thenScope, thenBranch, true, thenInfo); if (type != null && JetStandardClasses.isNothing(type)) { resultDataFlowInfo = elseInfo; // resultScope = elseScope; @@ -1470,7 +1490,7 @@ public class JetTypeInferrer { } } else if (thenBranch == null) { - JetType type = getType(scope, elseBranch, true, elseInfo); + JetType type = getTypeWithNewDataFlowInfo(scope, elseBranch, true, elseInfo); if (type != null && JetStandardClasses.isNothing(type)) { resultDataFlowInfo = thenInfo; // resultScope = thenScope; @@ -1478,8 +1498,8 @@ public class JetTypeInferrer { result = JetStandardClasses.getUnitType(); } else { - JetType thenType = getType(thenScope, thenBranch, true, thenInfo); - JetType elseType = getType(scope, elseBranch, true, elseInfo); + JetType thenType = getTypeWithNewDataFlowInfo(thenScope, thenBranch, true, thenInfo); + JetType elseType = getTypeWithNewDataFlowInfo(scope, elseBranch, true, elseInfo); if (thenType == null) { result = elseType; @@ -1647,9 +1667,9 @@ public class JetTypeInferrer { checkCondition(scope, condition); JetExpression body = expression.getBody(); if (body != null) { - WritableScopeImpl scopeToExtend = newWritableScopeImpl(); + WritableScopeImpl scopeToExtend = newWritableScopeImpl().setDebugName("Scope extended in while's condition"); DataFlowInfo conditionInfo = condition == null ? dataFlowInfo : extractDataFlowInfoFromCondition(condition, true, scopeToExtend); - getType(scopeToExtend, body, true, conditionInfo); + getTypeWithNewDataFlowInfo(scopeToExtend, body, true, conditionInfo); } if (!flowInformationProvider.isBreakable(expression)) { // resultScope = newWritableScopeImpl(); @@ -1665,18 +1685,18 @@ public class JetTypeInferrer { if (body instanceof JetFunctionLiteralExpression) { JetFunctionLiteralExpression function = (JetFunctionLiteralExpression) body; if (!function.hasParameterSpecification()) { - WritableScope writableScope = newWritableScopeImpl(); + WritableScope writableScope = newWritableScopeImpl().setDebugName("do..while body scope"); conditionScope = writableScope; - getBlockReturnedTypeWithWritableScope(writableScope, function.getBody(), dataFlowInfo, extectedReturnType); + getBlockReturnedTypeWithWritableScope(writableScope, function.getBody(), dataFlowInfo, expectedReturnType); trace.recordBlock(function); } else { getType(scope, body, true); } } else if (body != null) { - WritableScope writableScope = newWritableScopeImpl(); + WritableScope writableScope = newWritableScopeImpl().setDebugName("do..while body scope"); conditionScope = writableScope; - getBlockReturnedTypeWithWritableScope(writableScope, Collections.singletonList(body), dataFlowInfo, extectedReturnType); + getBlockReturnedTypeWithWritableScope(writableScope, Collections.singletonList(body), dataFlowInfo, expectedReturnType); } JetExpression condition = expression.getCondition(); checkCondition(conditionScope, condition); @@ -1708,7 +1728,7 @@ public class JetTypeInferrer { expectedParameterType = checkIterableConvention(loopRangeType, loopRange.getNode()); } - WritableScope loopScope = newWritableScopeImpl(); + WritableScope loopScope = newWritableScopeImpl().setDebugName("Scope with for-loop index"); if (loopParameter != null) { JetTypeReference typeReference = loopParameter.getTypeReference(); @@ -1811,8 +1831,82 @@ public class JetTypeInferrer { // // TODO : type argument inference // JetTypeReference typeReference = expression.getTypeReference(); // if (typeReference != null) { -// result = checkConstructorCall(scope, typeReference, expression); +// result = checkTypeInitializerCall(scope, typeReference, expression); // } +// } + +// private void resolveCallWithExplicitName(@NotNull JetScope scope, JetExpression receiver, String functionName, List resolvedTypeArguments, List valueArguments) { +// +// boolean someNamed = false; +// boolean allNamed = true; +// for (ValueArgumentPsi valueArgument : valueArguments) { +// if (valueArgument.isNamed()) { +// trace.getErrorHandler().genericError(valueArgument.asElement().getNode(), "Named arguments are not supported"); +// someNamed = true; +// } +// else { +// allNamed = false; +// } +// } +// if (someNamed) { +// return; // TODO +// } +// if (someNamed && !allNamed) { +// // TODO function literals outside parentheses +// } +// +// ErrorHandlerWithRegions errorHandler = trace.getErrorHandler(); +// +// // 1. resolve 'receiver' in 'scope' with expected type 'NO_EXPECTED_TYPE' +// errorHandler.openRegion(); +// JetType receiverType = JetTypeInferrer.this.getType(scope, receiver, false, NO_EXPECTED_TYPE); +// // for each applicable function in 'receiverType' +// Set allFunctions = receiverType.getMemberScope().getFunctionGroup(functionName).getFunctionDescriptors(); +// Map> applicableFunctions = Maps.newHashMap(); +// int typeArgCount = resolvedTypeArguments.size(); +// int valueArgCount = valueArguments.size(); +// for (FunctionDescriptor functionDescriptor : allFunctions) { +// if (typeArgCount == 0 || functionDescriptor.getTypeParameters().size() == typeArgCount) { +// if (FunctionDescriptorUtil.getMinimumArity(functionDescriptor) <= valueArgCount && +// valueArgCount <= FunctionDescriptorUtil.getMaximumArity(functionDescriptor)) { +// // get expected types for value parameters +// if (typeArgCount > 0) { +// FunctionDescriptor substitutedFunctionDescriptor = FunctionDescriptorUtil.substituteFunctionDescriptor(resolvedTypeArguments, functionDescriptor); +// } +// else { +// FunctionDescriptor substitutedFunctionDescriptor = FunctionDescriptorUtil.substituteFunctionDescriptor(TypeUtils.getDefaultTypes(functionDescriptor.getTypeParameters()), functionDescriptor); +// List valueArgumentTypes = getArgumentTypes(substitutedFunctionDescriptor, valueArguments); +// if (valueArgumentTypes == null) { +// Map noExpectedTypes = Maps.newHashMap(); +// for (TypeParameterDescriptor typeParameterDescriptor : functionDescriptor.getTypeParameters()) { +// noExpectedTypes.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjection(NO_EXPECTED_TYPE)); +// } +// substitutedFunctionDescriptor = functionDescriptor.substitute(TypeSubstitutor.create(noExpectedTypes)); +// valueArgumentTypes = getArgumentTypes(substitutedFunctionDescriptor, valueArguments); +// } +// if (valueArgumentTypes != null) { +// List typeArguments = solveConstraintSystem(functionDescriptor, valueArgumentTypes, expectedReturnType); +// if (typeArguments != null) { +// applicableFunctions.put(functionDescriptor, typeArguments); +// } +// } +// } +// // type-check the parameters +// // if something was found (one or many options +// errorHandler.closeAndCommitCurrentRegion(); +// // otherwise +// errorHandler.closeAndReturnCurrentRegion(); +// +// } +// } +// } +// // get expected types for value parameters +// // type-check the parameters +// // if something was found (one or many options +// errorHandler.closeAndCommitCurrentRegion(); +// // otherwise +// errorHandler.closeAndReturnCurrentRegion(); +// // } @Override @@ -1825,7 +1919,7 @@ public class JetTypeInferrer { // TODO : functions as values JetExpression selectorExpression = expression.getSelectorExpression(); JetExpression receiverExpression = expression.getReceiverExpression(); - JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false, dataFlowInfo, null, null).getType(receiverExpression); + JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false, dataFlowInfo, NO_EXPECTED_TYPE, null).getType(receiverExpression); if (receiverType != null) { ErrorHandlerWithRegions errorHandler = trace.getErrorHandler(); errorHandler.openRegion(); @@ -1989,7 +2083,7 @@ public class JetTypeInferrer { JetType knownType = getType(scope, expression.getLeftHandSide(), false); JetPattern pattern = expression.getPattern(); if (pattern != null && knownType != null) { - WritableScopeImpl scopeToExtend = newWritableScopeImpl(); + WritableScopeImpl scopeToExtend = newWritableScopeImpl().setDebugName("Scope extended in 'is'"); DataFlowInfo newDataFlowInfo = checkPatternType(pattern, knownType, scopeToExtend, getVariableDescriptorFromSimpleName(expression.getLeftHandSide())); patternsToDataFlowInfo.put(pattern, newDataFlowInfo); patternsToBoundVariableLists.put(pattern, scopeToExtend.getDeclaredVariables()); @@ -2114,10 +2208,10 @@ public class JetTypeInferrer { } else if (operationType == JetTokens.ANDAND || operationType == JetTokens.OROR) { JetType leftType = getType(scope, left, false); - WritableScopeImpl leftScope = newWritableScopeImpl(); + WritableScopeImpl leftScope = newWritableScopeImpl().setDebugName("Left scope of && or ||"); DataFlowInfo flowInfoLeft = extractDataFlowInfoFromCondition(left, operationType == JetTokens.ANDAND, leftScope); // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition - WritableScopeImpl rightScope = operationType == JetTokens.ANDAND ? leftScope : newWritableScopeImpl(); - JetType rightType = right == null ? null : getType(rightScope, right, false, flowInfoLeft); + WritableScopeImpl rightScope = operationType == JetTokens.ANDAND ? leftScope : newWritableScopeImpl().setDebugName("Right scope of && or ||"); + JetType rightType = right == null ? null : getTypeWithNewDataFlowInfo(rightScope, right, false, flowInfoLeft); if (leftType != null && !isBoolean(leftType)) { trace.getErrorHandler().typeMismatch(left, semanticServices.getStandardLibrary().getBooleanType(), leftType); } @@ -2202,7 +2296,7 @@ public class JetTypeInferrer { @Nullable protected List getTypes(JetScope scope, List indexExpressions) { List argumentTypes = new ArrayList(); - TypeInferrerVisitor typeInferrerVisitor = new TypeInferrerVisitor(scope, false, dataFlowInfo, null, null); + TypeInferrerVisitor typeInferrerVisitor = new TypeInferrerVisitor(scope, false, dataFlowInfo, NO_EXPECTED_TYPE, null); for (JetExpression indexExpression : indexExpressions) { JetType type = typeInferrerVisitor.getType(indexExpression); if (type == null) { @@ -2293,7 +2387,7 @@ public class JetTypeInferrer { } private class TypeInferrerVisitorWithNamespaces extends TypeInferrerVisitor { - private TypeInferrerVisitorWithNamespaces(@NotNull JetScope scope, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo, @Nullable JetType expectedType, @Nullable JetType expectedReturnType) { + private TypeInferrerVisitorWithNamespaces(@NotNull JetScope scope, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo, @NotNull JetType expectedType, @Nullable JetType expectedReturnType) { super(scope, preferBlock, dataFlowInfo, expectedType, expectedReturnType); } @@ -2304,7 +2398,7 @@ public class JetTypeInferrer { @NotNull @Override - public TypeInferrerVisitor createNew(@NotNull JetScope scope, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo, @Nullable JetType expectedType, @Nullable JetType expectedReturnType) { + public TypeInferrerVisitor createNew(@NotNull JetScope scope, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo, @NotNull JetType expectedType, @Nullable JetType expectedReturnType) { return new TypeInferrerVisitorWithNamespaces(scope, preferBlock, dataFlowInfo, expectedType, expectedReturnType); } @@ -2324,7 +2418,7 @@ public class JetTypeInferrer { private class TypeInferrerVisitorWithWritableScope extends TypeInferrerVisitor { private final WritableScope scope; - public TypeInferrerVisitorWithWritableScope(@NotNull WritableScope scope, boolean preferBlock, DataFlowInfo dataFlowInfo, @Nullable JetType expectedType, @Nullable JetType expectedReturnType) { + public TypeInferrerVisitorWithWritableScope(@NotNull WritableScope scope, boolean preferBlock, DataFlowInfo dataFlowInfo, @NotNull JetType expectedType, @Nullable JetType expectedReturnType) { super(scope, preferBlock, dataFlowInfo, expectedType, expectedReturnType); this.scope = scope; } @@ -2459,8 +2553,8 @@ public class JetTypeInferrer { @NotNull @Override - public TypeInferrerVisitor createNew(@NotNull JetScope scope, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo, @Nullable JetType expectedType, @Nullable JetType expectedReturnType) { - WritableScopeImpl writableScope = newWritableScopeImpl(scope); + public TypeInferrerVisitor createNew(@NotNull JetScope scope, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo, @NotNull JetType expectedType, @Nullable JetType expectedReturnType) { + WritableScopeImpl writableScope = newWritableScopeImpl(scope).setDebugName("Block scope"); return new TypeInferrerVisitorWithWritableScope(writableScope, preferBlock, dataFlowInfo, expectedType, expectedReturnType); } } diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java b/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java index 327a064e7df..34ada968d38 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -177,7 +177,7 @@ public class TypeUtils { @NotNull public static JetType makeUnsubstitutedType(ClassDescriptor classDescriptor, JetScope unsubstitutedMemberScope) { - List arguments = getDefaultArguments(classDescriptor.getTypeConstructor().getParameters()); + List arguments = getDefaultTypeProjections(classDescriptor.getTypeConstructor().getParameters()); return new JetTypeImpl( Collections.emptyList(), classDescriptor.getTypeConstructor(), @@ -188,7 +188,7 @@ public class TypeUtils { } @NotNull - public static List getDefaultArguments(List parameters) { + public static List getDefaultTypeProjections(List parameters) { List result = new ArrayList(); for (TypeParameterDescriptor parameterDescriptor : parameters) { result.add(new TypeProjection(parameterDescriptor.getDefaultType())); @@ -196,6 +196,15 @@ public class TypeUtils { return result; } + @NotNull + public static List getDefaultTypes(List parameters) { + List result = Lists.newArrayList(); + for (TypeParameterDescriptor parameterDescriptor : parameters) { + result.add(parameterDescriptor.getDefaultType()); + } + return result; + } + @NotNull public static Map buildSubstitutionContext(@NotNull JetType context) { return buildSubstitutionContext(context.getConstructor().getParameters(), context.getArguments()); diff --git a/idea/tests/org/jetbrains/jet/JetTestUtils.java b/idea/tests/org/jetbrains/jet/JetTestUtils.java index 7fcce005b14..b2309e1f09e 100644 --- a/idea/tests/org/jetbrains/jet/JetTestUtils.java +++ b/idea/tests/org/jetbrains/jet/JetTestUtils.java @@ -61,10 +61,6 @@ public class JetTestUtils { public void removeStatementRecord(@NotNull JetElement statement) { } - @Override - public void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression) { - } - @Override public void requireBackingField(@NotNull PropertyDescriptor propertyDescriptor) { } diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 3372bca02a4..4228276fffd 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -493,14 +493,14 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { private void assertType(String expression, JetType expectedType) { Project project = getProject(); JetExpression jetExpression = JetChangeUtil.createExpression(project, expression); - JetType type = semanticServices.getTypeInferrer(JetTestUtils.DUMMY, JetFlowInformationProvider.NONE).getType(classDefinitions.BASIC_SCOPE, jetExpression, false, null); + JetType type = semanticServices.getTypeInferrer(JetTestUtils.DUMMY, JetFlowInformationProvider.NONE).getType(classDefinitions.BASIC_SCOPE, jetExpression, false, JetTypeInferrer.NO_EXPECTED_TYPE); assertTrue(type + " != " + expectedType, type.equals(expectedType)); } private void assertErrorType(String expression) { Project project = getProject(); JetExpression jetExpression = JetChangeUtil.createExpression(project, expression); - JetType type = semanticServices.getTypeInferrer(JetTestUtils.DUMMY, JetFlowInformationProvider.NONE).safeGetType(classDefinitions.BASIC_SCOPE, jetExpression, false, null); + JetType type = semanticServices.getTypeInferrer(JetTestUtils.DUMMY, JetFlowInformationProvider.NONE).safeGetType(classDefinitions.BASIC_SCOPE, jetExpression, false, JetTypeInferrer.NO_EXPECTED_TYPE); assertTrue("Error type expected but " + type + " returned", ErrorUtils.isErrorType(type)); } @@ -523,7 +523,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { private void assertType(JetScope scope, String expression, String expectedTypeStr) { Project project = getProject(); JetExpression jetExpression = JetChangeUtil.createExpression(project, expression); - JetType type = semanticServices.getTypeInferrer(JetTestUtils.DUMMY, JetFlowInformationProvider.NONE).getType(scope, jetExpression, false, null); + JetType type = semanticServices.getTypeInferrer(JetTestUtils.DUMMY, JetFlowInformationProvider.NONE).getType(scope, jetExpression, false, JetTypeInferrer.NO_EXPECTED_TYPE); JetType expectedType = expectedTypeStr == null ? null : makeType(expectedTypeStr); assertEquals(expectedType, type); }