private void computeDeferredTypes() { Collection<Box<DeferredType>> deferredTypes = trace.getKeys(DEFERRED_TYPE); if (deferredTypes != null) { // +1 is a work around agains new Queue(0).addLast(...) bug // stepan.koltsov@ 2011-11-21 final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size() + 1); trace.addHandler( DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<Box<DeferredType>, Boolean>() { @Override public void handleRecord( WritableSlice<Box<DeferredType>, Boolean> deferredTypeKeyDeferredTypeWritableSlice, Box<DeferredType> key, Boolean value) { queue.addLast(key.getData()); } }); for (Box<DeferredType> deferredType : deferredTypes) { queue.addLast(deferredType.getData()); } while (!queue.isEmpty()) { DeferredType deferredType = queue.pullFirst(); if (!deferredType.isComputed()) { try { deferredType.getActualType(); // to compute } catch (ReenteringLazyValueComputationException e) { // A problem should be reported while computing the type } } } } }
// allowedFinalSupertypes typically contains a enum type of which supertypeOwner is an entry private void checkSupertypeList( @NotNull MutableClassDescriptor supertypeOwner, @NotNull Map<JetTypeReference, JetType> supertypes, Set<TypeConstructor> allowedFinalSupertypes) { Set<TypeConstructor> typeConstructors = Sets.newHashSet(); boolean classAppeared = false; for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) { JetTypeReference typeReference = entry.getKey(); JetType supertype = entry.getValue(); ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); if (classDescriptor != null) { if (classDescriptor.getKind() != ClassKind.TRAIT) { if (classAppeared) { trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference)); } else { classAppeared = true; } } } else { trace.report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference)); } TypeConstructor constructor = supertype.getConstructor(); if (!typeConstructors.add(constructor)) { trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference)); } if (constructor.isSealed() && !allowedFinalSupertypes.contains(constructor)) { trace.report(FINAL_SUPERTYPE.on(typeReference)); } } }
@Override public JetTypeInfo visitObjectLiteralExpression( @NotNull final JetObjectLiteralExpression expression, final ExpressionTypingContext context) { DelegatingBindingTrace delegatingBindingTrace = context.trace.get(TRACE_DELTAS_CACHE, expression.getObjectDeclaration()); if (delegatingBindingTrace != null) { delegatingBindingTrace.addAllMyDataTo(context.trace); JetType type = context.trace.get(EXPRESSION_TYPE, expression); return DataFlowUtils.checkType(type, expression, context, context.dataFlowInfo); } final JetType[] result = new JetType[1]; final TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create( context.trace, "trace to resolve object literal expression", expression); ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor> handler = new ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor>() { @Override public void handleRecord( WritableSlice<PsiElement, ClassDescriptor> slice, PsiElement declaration, final ClassDescriptor descriptor) { if (slice == CLASS && declaration == expression.getObjectDeclaration()) { JetType defaultType = DeferredType.create( context.trace, createRecursionIntolerantLazyValueWithDefault( ErrorUtils.createErrorType("Recursive dependency"), new Function0<JetType>() { @Override public JetType invoke() { return descriptor.getDefaultType(); } })); result[0] = defaultType; if (!context.trace.get(PROCESSED, expression)) { temporaryTrace.record(EXPRESSION_TYPE, expression, defaultType); temporaryTrace.record(PROCESSED, expression); } } } }; ObservableBindingTrace traceAdapter = new ObservableBindingTrace(temporaryTrace); traceAdapter.addHandler(CLASS, handler); TopDownAnalyzer.processClassOrObject( context.replaceBindingTrace(traceAdapter).replaceContextDependency(INDEPENDENT), context.scope.getContainingDeclaration(), expression.getObjectDeclaration()); DelegatingBindingTrace cloneDelta = new DelegatingBindingTrace( new BindingTraceContext().getBindingContext(), "cached delta trace for object literal expression resolve", expression); temporaryTrace.addAllMyDataTo(cloneDelta); context.trace.record(TRACE_DELTAS_CACHE, expression.getObjectDeclaration(), cloneDelta); temporaryTrace.commit(); return DataFlowUtils.checkType(result[0], expression, context, context.dataFlowInfo); }
private void resolveAnonymousInitializers( JetClassOrObject jetClassOrObject, MutableClassDescriptor classDescriptor) { if (!context.completeAnalysisNeeded(jetClassOrObject)) return; List<JetClassInitializer> anonymousInitializers = jetClassOrObject.getAnonymousInitializers(); if (classDescriptor.getUnsubstitutedPrimaryConstructor() != null) { ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); assert primaryConstructor != null; final JetScope scopeForInitializers = classDescriptor.getScopeForInitializers(); for (JetClassInitializer anonymousInitializer : anonymousInitializers) { expressionTypingServices.getType( scopeForInitializers, anonymousInitializer.getBody(), NO_EXPECTED_TYPE, trace); } } else { for (JetClassInitializer anonymousInitializer : anonymousInitializers) { trace.report(ANONYMOUS_INITIALIZER_WITHOUT_CONSTRUCTOR.on(anonymousInitializer)); } } }
private void resolveSecondaryConstructorBody( JetSecondaryConstructor declaration, final ConstructorDescriptor descriptor) { if (!context.completeAnalysisNeeded(declaration)) return; MutableClassDescriptor classDescriptor = (MutableClassDescriptor) descriptor.getContainingDeclaration(); final JetScope scopeForSupertypeInitializers = FunctionDescriptorUtil.getFunctionInnerScope( classDescriptor.getScopeForSupertypeResolution(), descriptor, trace); // contains only constructor parameters final JetScope scopeForConstructorBody = FunctionDescriptorUtil.getFunctionInnerScope( classDescriptor.getScopeForInitializers(), descriptor, trace); // contains members & backing fields final DataFlowInfo dataFlowInfo = DataFlowInfo.EMPTY; // TODO: dataFlowInfo PsiElement nameElement = declaration.getNameNode().getPsi(); if (classDescriptor.getUnsubstitutedPrimaryConstructor() == null) { trace.report(SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY.on(nameElement)); } else { List<JetDelegationSpecifier> initializers = declaration.getInitializers(); if (initializers.isEmpty()) { trace.report(SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST.on(nameElement)); } else { initializers .get(0) .accept( new JetVisitorVoid() { @Override public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { JetTypeReference typeReference = call.getTypeReference(); if (typeReference != null) { callResolver.resolveFunctionCall( trace, scopeForSupertypeInitializers, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo); } } @Override public void visitDelegationToThisCall(JetDelegatorToThisCall call) { // TODO : check that there's no recursion in this() calls // TODO : check: if a this() call is present, no other initializers are allowed ClassDescriptor classDescriptor = descriptor.getContainingDeclaration(); callResolver.resolveFunctionCall( trace, scopeForSupertypeInitializers, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo); // call.getThisReference(), // classDescriptor, // classDescriptor.getDefaultType(), // call); // trace.getErrorHandler().genericError(call.getNode(), // "this-calls are not supported"); } @Override public void visitDelegationByExpressionSpecifier( JetDelegatorByExpressionSpecifier specifier) { trace.report(BY_IN_SECONDARY_CONSTRUCTOR.on(specifier)); } @Override public void visitDelegationToSuperClassSpecifier( JetDelegatorToSuperClass specifier) { trace.report(INITIALIZER_WITH_NO_ARGUMENTS.on(specifier)); } @Override public void visitDelegationSpecifier(JetDelegationSpecifier specifier) { throw new IllegalStateException(); } }); for (int i = 1, initializersSize = initializers.size(); i < initializersSize; i++) { JetDelegationSpecifier initializer = initializers.get(i); trace.report(MANY_CALLS_TO_THIS.on(initializer)); } } } JetExpression bodyExpression = declaration.getBodyExpression(); if (bodyExpression != null) { expressionTypingServices.checkFunctionReturnType( scopeForConstructorBody, declaration, descriptor, JetStandardClasses.getUnitType(), trace); } checkDefaultParameterValues( declaration.getValueParameters(), descriptor.getValueParameters(), scopeForConstructorBody); }