/** * Collapse <code>structECR</code> by merge it with all its element ECRs, and set its type as the * cell type (simple type might with top size) * * @param structECR * @param structT * @param ECRCache avoid structure cycle * @return */ private ValueType collapseStruct(ECR structECR, StructType structT, Collection<ECR> ECRCache) { // Ensure collapsed type to be simple ValueType unionType = null; // join components Collection<ECR> elems = structT.getFieldMap().asMapOfRanges().values(); Collection<ECR> cjoins = Sets.newHashSet(); Collection<Pair<Size, ECR>> ccjoins = Sets.newHashSet(); for (ECR elem : elems) { ECR elemLoc = getLoc(elem); ValueType elemLocType = getType(elemLoc); Parent parent = elemLocType.getParent().removeECR(structECR); elemLocType.setParent(parent); if (!ECRCache.add(elemLoc)) continue; // ECRCache has elemLoc cjoins.addAll(getCjoins(elemLoc)); elemLoc.clearCCjoins(ccjoins); ccjoins.addAll(getCCjoins(elemLoc)); elemLoc.clearCCjoins(ccjoins); if (elemLocType.isStruct()) { elemLocType = collapseStruct(elemLoc, elemLocType.asStruct(), ECRCache); } union(structECR, elemLoc); unionType = unionType == null ? elemLocType : unify(unionType, elemLocType); } unionType = unionType == null ? ValueType.bottom() : unionType; setType(structECR, unionType); ECR root = findRoot(structECR); for (Pair<Size, ECR> cjoinPair : ccjoins) ccjoin(cjoinPair.fst(), root, cjoinPair.snd()); for (ECR joinECR : cjoins) cjoin(root, joinECR); return unionType; }