@Override
 protected void appendContent(StringBuilder result, String indentation) {
   super.appendContent(result, indentation);
   result.append("\n" + indentation + "parent: [");
   parent.appendContent(result, indentation + "  ");
   closeBracket(result, indentation);
 }
 protected void mergeExpressionTypesIntoParent(ResolvedTypes parent) {
   Map<XExpression, List<TypeData>> expressionTypes = basicGetExpressionTypes();
   if (!expressionTypes.isEmpty()) {
     for (Map.Entry<XExpression, List<TypeData>> entry : expressionTypes.entrySet()) {
       List<TypeData> list = entry.getValue();
       for (int i = 0, size = list.size(); i < size; i++) {
         parent.acceptType(entry.getKey(), prepareMerge(list.get(i), parent.getReferenceOwner()));
       }
     }
   }
 }
 @Override
 public void addDeclaredTypeParameters(List<JvmTypeParameter> typeParameters) {
   if (typeParameters.isEmpty()) return;
   List<JvmTypeParameter> list = basicGetDeclardTypeParameters();
   if (list == null) {
     super.addDeclaredTypeParameters(parent.getDeclaredTypeParameters());
     getDeclaredTypeParameters().addAll(typeParameters);
   } else {
     list.addAll(typeParameters);
   }
 }
 protected void mergeTypesIntoParent(ResolvedTypes parent) {
   Map<JvmIdentifiableElement, LightweightTypeReference> types = basicGetTypes();
   if (!types.isEmpty()) {
     for (Map.Entry<JvmIdentifiableElement, LightweightTypeReference> entry : types.entrySet()) {
       LightweightTypeReference value = entry.getValue();
       if (value instanceof UnboundTypeReference
           && super.isResolved(((UnboundTypeReference) value).getHandle())) {
         parent.setType(
             entry.getKey(), value.getUpperBoundSubstitute().copyInto(parent.getReferenceOwner()));
       } else {
         parent.setType(entry.getKey(), value.copyInto(parent.getReferenceOwner()));
       }
     }
   }
 }
 @Override
 protected boolean isRefinedType(JvmIdentifiableElement element) {
   if (super.isRefinedType(element)) {
     return true;
   }
   return parent.isRefinedType(element);
 }
 @Override
 /* @Nullable */
 protected Map<JvmIdentifiableElement, LightweightTypeReference> getFlattenedReassignedTypes() {
   if (flattenedReassignedTypes != null) {
     // already computed
     return flattenedReassignedTypes.orNull();
   }
   Map<JvmIdentifiableElement, LightweightTypeReference> result =
       parent.getFlattenedReassignedTypes();
   if (result == null) {
     // parent doesn't have reassigned types
     // use only locally reassigned types
     return (flattenedReassignedTypes = Optional.fromNullable(super.getFlattenedReassignedTypes()))
         .orNull();
   }
   Map<JvmIdentifiableElement, LightweightTypeReference> myReassignedTypes =
       basicGetReassignedTypes();
   if (myReassignedTypes.isEmpty()) {
     // no locally reassigned types, use result from parent which was already checked for null
     return (flattenedReassignedTypes = Optional.of(result)).orNull();
   }
   // merge parent's reassigned types and locally reassigned types
   result = Maps.newHashMap(result);
   result.putAll(myReassignedTypes);
   return (flattenedReassignedTypes = Optional.of(result)).orNull();
 }
 @Override
 public boolean isRefinedType(XExpression expression) {
   if (super.isRefinedType(expression)) {
     return true;
   }
   return parent.isRefinedType(expression);
 }
 @Override
 protected boolean isPropagatedType(XExpression expression) {
   if (super.isPropagatedType(expression)) {
     return true;
   }
   return parent.isPropagatedType(expression);
 }
 public void replaceDeclaredTypeParameters(List<JvmTypeParameter> typeParameters) {
   List<JvmTypeParameter> list = basicGetDeclardTypeParameters();
   if (list != null) {
     throw new IllegalStateException(
         "Cannot replace declared type parameters if there are already type parameters in this StackedResolvedTypes");
   }
   super.addDeclaredTypeParameters(typeParameters);
 }
 @Override
 /* @Nullable */
 protected JvmIdentifiableElement doGetLinkedFeature(
     /* @Nullable */ XExpression featureOrConstructorCall) {
   JvmIdentifiableElement result = super.doGetLinkedFeature(featureOrConstructorCall);
   if (result != null) return result;
   return parent.doGetLinkedFeature(featureOrConstructorCall);
 }
 @Override
 /* @Nullable */
 protected IApplicableCandidate doGetCandidate(
     /* @Nullable */ XExpression featureOrConstructorCall) {
   IApplicableCandidate result = super.doGetCandidate(featureOrConstructorCall);
   if (result != null) return result;
   return parent.doGetCandidate(featureOrConstructorCall);
 }
 protected void mergeLinkingCandidatesIntoParent(ResolvedTypes parent) {
   Map<XExpression, IApplicableCandidate> linkingCandidates = basicGetLinkingMap();
   if (!linkingCandidates.isEmpty()) {
     for (Map.Entry<XExpression, IApplicableCandidate> entry : linkingCandidates.entrySet()) {
       parent.acceptCandidate(entry.getKey(), entry.getValue());
     }
   }
 }
 @Override
 /* @Nullable */
 protected List<TypeData> doGetTypeData(XExpression expression) {
   List<TypeData> result = super.doGetTypeData(expression);
   if (result == null) {
     result = parent.doGetTypeData(expression);
   }
   return result;
 }
 @Override
 /* @Nullable */
 protected List<LightweightTypeReference> doGetActualTypeArguments(XExpression expression) {
   List<LightweightTypeReference> result = super.doGetActualTypeArguments(expression);
   if (result == null) {
     result = parent.doGetActualTypeArguments(expression);
   }
   return result;
 }
 @Override
 public void reassignType(
     JvmIdentifiableElement identifiable, /* @Nullable */ LightweightTypeReference reference) {
   super.reassignType(identifiable, reference);
   if (reference == null) {
     getParent().reassignType(identifiable, reference);
   }
   flattenedReassignedTypes = null;
 }
 @Override
 protected void refineExpectedType(XExpression receiver, ITypeExpectation refinedExpectation) {
   Collection<TypeData> typeData = basicGetExpressionTypes().get(receiver);
   if (typeData == null) {
     getParent().refineExpectedType(receiver, refinedExpectation);
   } else {
     super.refineExpectedType(receiver, refinedExpectation);
   }
 }
 @Override
 /* @Nullable */
 protected IConstructorLinkingCandidate doGetConstructor(XConstructorCall constructorCall) {
   IConstructorLinkingCandidate result = super.doGetConstructor(constructorCall);
   if (result == null) {
     result = parent.doGetConstructor(constructorCall);
   }
   return result;
 }
 @Override
 /* @Nullable */
 protected IFeatureLinkingCandidate doGetFeature(XAbstractFeatureCall featureCall) {
   IFeatureLinkingCandidate result = super.doGetFeature(featureCall);
   if (result == null) {
     result = parent.doGetFeature(featureCall);
   }
   return result;
 }
 @Override
 /* @Nullable */
 protected LightweightTypeReference doGetActualTypeNoDeclaration(
     JvmIdentifiableElement identifiable, boolean ignoreReassignedTypes) {
   LightweightTypeReference result =
       super.doGetActualTypeNoDeclaration(identifiable, ignoreReassignedTypes);
   if (result == null) {
     result = parent.doGetActualTypeNoDeclaration(identifiable, ignoreReassignedTypes);
   }
   return result;
 }
 @Override
 protected UnboundTypeReference getUnboundTypeReference(Object handle) {
   UnboundTypeReference result = basicGetTypeParameters().get(handle);
   if (result == null) {
     result = parent.getUnboundTypeReference(handle);
     if (result.internalIsResolved())
       throw new IllegalStateException("Cannot query unbound reference that was already resolved");
     return (UnboundTypeReference) result.copyInto(getReferenceOwner());
   }
   return result;
 }
 protected void mergeTypeParametersIntoParent(ResolvedTypes parent) {
   for (UnboundTypeReference unbound : basicGetTypeParameters().values()) {
     LightweightTypeReference resolvedTo = unbound.getResolvedTo();
     if (resolvedTo == null) {
       List<JvmTypeParameter> typeParameters = basicGetDeclardTypeParameters();
       if (typeParameters != null && typeParameters.contains(unbound.getTypeParameter())) {
         unbound.tryResolve();
         if (!unbound.internalIsResolved()) {
           if (unbound.getExpression() instanceof XConstructorCall) {
             unbound.resolve(); // resolve against constraints
           } else {
             unbound.acceptHint(
                 unbound.getOwner().newParameterizedTypeReference(unbound.getTypeParameter()),
                 BoundTypeArgumentSource.RESOLVED,
                 unbound,
                 VarianceInfo.INVARIANT,
                 VarianceInfo.INVARIANT);
           }
         }
       } else {
         LightweightTypeReference reference = unbound.copyInto(parent.getReferenceOwner());
         if (reference instanceof UnboundTypeReference) {
           parent.acceptUnboundTypeReference(
               unbound.getHandle(), (UnboundTypeReference) reference);
         }
       }
     }
   }
   Map<Object, List<LightweightBoundTypeArgument>> typeParameterHints =
       basicGetTypeParameterHints();
   for (Map.Entry<Object, List<LightweightBoundTypeArgument>> hint :
       typeParameterHints.entrySet()) {
     if (!parent.isResolved(hint.getKey())) {
       List<LightweightBoundTypeArgument> boundTypeArguments = hint.getValue();
       for (LightweightBoundTypeArgument boundTypeArgument : boundTypeArguments) {
         if (boundTypeArgument.getOrigin() instanceof VarianceInfo) {
           parent.acceptHint(hint.getKey(), boundTypeArgument);
         } else {
           LightweightBoundTypeArgument copy =
               new LightweightBoundTypeArgument(
                   boundTypeArgument.getTypeReference().copyInto(parent.getReferenceOwner()),
                   boundTypeArgument.getSource(),
                   boundTypeArgument.getOrigin(),
                   boundTypeArgument.getDeclaredVariance(),
                   boundTypeArgument.getActualVariance());
           parent.acceptHint(hint.getKey(), copy);
         }
       }
     }
   }
 }
 private Model modelBuilder(
     ResolvedType propertiesHost,
     Map<String, ModelProperty> properties,
     ModelContext modelContext) {
   String typeName =
       typeNameExtractor.typeName(ModelContext.fromParent(modelContext, propertiesHost));
   modelContext
       .getBuilder()
       .id(typeName)
       .type(propertiesHost)
       .name(typeName)
       .qualifiedType(ResolvedTypes.simpleQualifiedTypeName(propertiesHost))
       .properties(properties)
       .description("")
       .baseModel("")
       .discriminator("")
       .subTypes(new ArrayList<String>());
   return schemaPluginsManager.model(modelContext);
 }
 private Optional<Model> mapModel(ModelContext parentContext, ResolvedType resolvedType) {
   if (isMapType(resolvedType) && !parentContext.hasSeenBefore(resolvedType)) {
     String typeName = typeNameExtractor.typeName(parentContext);
     return Optional.of(
         parentContext
             .getBuilder()
             .id(typeName)
             .type(resolvedType)
             .name(typeName)
             .qualifiedType(ResolvedTypes.simpleQualifiedTypeName(resolvedType))
             .properties(new LinkedHashMap<String, ModelProperty>())
             .description("")
             .baseModel("")
             .discriminator("")
             .subTypes(new ArrayList<String>())
             .build());
   }
   return Optional.absent();
 }
 protected void mergeRefinedTypes(ResolvedTypes parent) {
   for (XExpression expression : basicGetRefinedTypes()) {
     parent.setRefinedType(expression);
   }
 }
 @Override
 protected void clear() {
   flattenedReassignedTypes = null;
   super.clear();
 }
 @Override
 protected void markToBeInferred(XExpression expression) {
   parent.markToBeInferred(expression);
 }
 @Override
 /* @Nullable */
 protected LightweightTypeReference getExpectedTypeForAssociatedExpression(
     JvmMember member, XExpression expression) {
   return parent.getExpectedTypeForAssociatedExpression(member, expression);
 }
 @Override
 public Collection<IAcceptor<? super IResolvedTypes>> getDeferredLogic() {
   List<IAcceptor<? super IResolvedTypes>> result = Lists.newArrayList(super.getDeferredLogic());
   result.addAll(parent.getDeferredLogic());
   return result;
 }
 @Override
 public List<AbstractDiagnostic> getQueuedDiagnostics() {
   List<AbstractDiagnostic> result = Lists.newArrayList(super.getQueuedDiagnostics());
   result.addAll(parent.getQueuedDiagnostics());
   return result;
 }
 @Override
 public List<JvmTypeParameter> getDeclaredTypeParameters() {
   List<JvmTypeParameter> result = basicGetDeclardTypeParameters();
   if (result != null) return result;
   return parent.getDeclaredTypeParameters();
 }