package jadx.core.dex.visitors.regions;

import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IBlock;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.LoopRegion;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.exceptions.JadxException;

import java.util.HashSet;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CheckRegions extends AbstractVisitor {
	private static final Logger LOG = LoggerFactory.getLogger(CheckRegions.class);

	@Override
	public void visit(MethodNode mth) throws JadxException {
		if (mth.isNoCode()
				|| mth.getBasicBlocks().isEmpty()
				|| mth.contains(AType.JADX_ERROR)) {
			return;
		}

		// check if all blocks included in regions
		final Set<BlockNode> blocksInRegions = new HashSet<BlockNode>();
		DepthRegionTraversal.traverseAll(mth, new AbstractRegionVisitor() {
			@Override
			public void processBlock(MethodNode mth, IBlock container) {
				if (container instanceof BlockNode) {
					blocksInRegions.add((BlockNode) container);
				}
			}
		});
		if (mth.getBasicBlocks().size() != blocksInRegions.size()) {
			for (BlockNode block : mth.getBasicBlocks()) {
				if (!blocksInRegions.contains(block)
						&& !block.getInstructions().isEmpty()
						&& !block.contains(AFlag.SKIP)) {
					mth.add(AFlag.INCONSISTENT_CODE);
					LOG.debug(" Missing block: {} in {}", block, mth);
				}
			}
		}

		// check loop conditions
		DepthRegionTraversal.traverseAll(mth, new AbstractRegionVisitor() {
			@Override
			public void enterRegion(MethodNode mth, IRegion region) {
				if (region instanceof LoopRegion) {
					BlockNode loopHeader = ((LoopRegion) region).getHeader();
					if (loopHeader != null && loopHeader.getInstructions().size() != 1) {
						ErrorsCounter.methodError(mth, "Incorrect condition in loop: " + loopHeader);
						mth.add(AFlag.INCONSISTENT_CODE);
					}
				}
			}
		});
	}
}

@@ -1127,16 +1127,18 @@
 %0A%09%09%09%09if 
+(!
 (contain
@@ -1161,24 +1161,25 @@
 ockNode)
+)
  %7B%0A%09%09%09%09%09
 blocksIn
@@ -1174,49 +1174,399 @@
 %09%09%09%09
-blocksInRegions.add((BlockNode) container
+return;%0A%09%09%09%09%7D%0A%09%09%09%09BlockNode block = (BlockNode) container;%0A%09%09%09%09if (blocksInRegions.add(block)) %7B%0A%09%09%09%09%09return;%0A%09%09%09%09%7D%0A%09%09%09%09if (!block.contains(AFlag.RETURN)%0A%09%09%09%09%09%09&& !block.contains(AFlag.SKIP)%0A%09%09%09%09%09%09&& !block.contains(AFlag.SYNTHETIC)%0A%09%09%09%09%09%09&& !block.getInstructions().isEmpty()) %7B%0A%09%09%09%09%09// TODO%0A%09%09%09%09%09// mth.add(AFlag.INCONSISTENT_CODE);%0A%09%09%09%09%09LOG.debug(%22 Duplicated block: %7B%7D in %7B%7D%22, block, mth
 );%0A%09

check for duplicated code generation