예제 #1
0
 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
         }
       }
     }
   }
 }
예제 #2
0
  // 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);
  }
예제 #4
0
 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));
     }
   }
 }
예제 #5
0
  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);
  }