@NonNull public Set<LayoutNode> canGrowLeft() { Set<LayoutNode> nodes; if (mToRight != null) { nodes = mToRight.canGrowLeft(); } else { nodes = new LinkedHashSet<LayoutNode>(); } if (!fixedWidth()) { nodes.add(this); } return nodes; }
@Override public void visitElement(@NonNull XmlContext context, @NonNull Element element) { // Traverse all child elements NodeList childNodes = element.getChildNodes(); int count = childNodes.getLength(); Map<String, LayoutNode> nodes = Maps.newHashMap(); for (int i = 0; i < count; i++) { Node node = childNodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { LayoutNode ln = new LayoutNode((Element) node, i); nodes.put(ln.getNodeId(), ln); } } // Node map is populated, recalculate nodes sizes for (LayoutNode ln : nodes.values()) { ln.processNode(nodes); } for (LayoutNode right : nodes.values()) { if (!right.mLastLeft || right.skip()) { continue; } Set<LayoutNode> canGrowLeft = right.canGrowLeft(); for (LayoutNode left : nodes.values()) { if (left == right || !left.mLastRight || left.skip() || !left.sameBucket(right)) { continue; } Set<LayoutNode> canGrowRight = left.canGrowRight(); if (canGrowLeft.size() > 0 || canGrowRight.size() > 0) { canGrowRight.addAll(canGrowLeft); LayoutNode nodeToBlame = right; LayoutNode otherNode = left; if (!canGrowRight.contains(right) && canGrowRight.contains(left)) { nodeToBlame = left; otherNode = right; } context.report( ISSUE, nodeToBlame.getNode(), context.getLocation(nodeToBlame.getNode()), String.format( "`%1$s` can overlap `%2$s` if %3$s %4$s due to localized text expansion", nodeToBlame.getNodeId(), otherNode.getNodeId(), Joiner.on(", ").join(canGrowRight), canGrowRight.size() > 1 ? "grow" : "grows")); } } } }