<commit_before>package sds.assemble.controlflow;

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.ArrayDeque;
import java.util.Deque;

import sds.assemble.MethodContent.ExceptionContent;
import sds.assemble.LineInstructions;

import static sds.assemble.controlflow.DominatorNodeSearcher.searchCommon;
import static sds.assemble.controlflow.CFNodeType.Entry;
import static sds.assemble.controlflow.CFNodeType.End;
import static sds.assemble.controlflow.CFNodeType.Exit;
import static sds.assemble.controlflow.CFNodeType.LoopEntry;
import static sds.assemble.controlflow.CFNodeType.LoopExit;
import static sds.assemble.controlflow.CFNodeType.StringSwitch;
import static sds.assemble.controlflow.CFNodeType.Switch;
import static sds.assemble.controlflow.CFEdgeType.JumpToCatch;
import static sds.assemble.controlflow.CFEdgeType.JumpToFinally;
import static sds.classfile.bytecode.MnemonicTable._goto;
import static sds.classfile.bytecode.MnemonicTable.goto_w;

/**
 * This builder class is for control flow graph.<br>
 * This class is designed singleton.
 * @author inagaki
 */
public class CFGBuilder {
	private static CFGBuilder builder = null;

	/**
	 * returns own instance.
	 * @return instance
	 */
	public static CFGBuilder getInstance() {
		if(builder == null) {
			builder = new CFGBuilder();
		}
		return builder;
	}

	/**
	 * returns control flow graph.
	 * @param inst method's instructions
	 * @param ex content of method's try-catch-finally
	 * @return control flow graph
	 */
	public CFNode[] build(LineInstructions[] inst, ExceptionContent ex) {
		/** 1. create nodes **/
		CFNode[] nodes = new CFNode[inst.length];
		for(int i = 0; i < nodes.length; i++) {
			nodes[i] = new CFNode(inst[i]);
		}
		
		/** 2. set parent and child, and investigate try-catch-finally **/
		int index = 0;
		for(CFNode n : nodes) {
			// processing for try-catch-finally
			boolean isGoto = (n.getStart().getOpcodeType() == _goto)
						  || (n.getStart().getOpcodeType() == goto_w);
			int[] tryIndex= ex.getIndexInRange(n.getStart().getPc(), false, isGoto);
			int[] catchTypeIndex = ex.getIndexInRange(n.getStart().getPc(), true, isGoto);
			if(tryIndex.length > 0) { // for catch
				n.inTry = true;
				for(int ti : tryIndex) {
					int catchIndex = ex.getTarget()[ti];
					for(int i = index; i < nodes.length; i++) {
						if(nodes[i].isInPcRange(catchIndex)) {
							nodes[i].isCatchEntry = true;
							n.addChild(nodes[i], JumpToCatch);
							nodes[i].addParent(n, JumpToCatch);
							break;
						}
					}
				}
			}
			if(catchTypeIndex.length > 0) { // for finally
				for(int ci : catchTypeIndex) {
					int finallyIndex = ex.getTarget()[ci];
					for(int i = index; i < nodes.length; i++) {
						if(nodes[i].isInPcRange(finallyIndex)) {
							nodes[i].isFinallyEntry = true;
							n.addChild(nodes[i], JumpToFinally);
							nodes[i].addParent(n, JumpToFinally);
							break;
						}
					}
				}
			}
			// processing for setting parent and child.
			if(index > 0) {
				CFNodeType type = nodes[index-1].getType();
				if(type != Exit && type != LoopExit && type != Switch && type != End) {
					n.addParent(nodes[index-1]);
					nodes[index-1].addChild(n);
				}
			} else if(index == nodes.length-1) {
				CFNodeType type = n.getType();
				if(type != Exit && type != LoopExit && type != Switch) {
					n.addChild(nodes[index]);
					nodes[index].addParent(n);
				}
			}
			index++;
		}

		/** 3. set jump point node **/
		index = 0;
		for(CFNode n : nodes) {
			CFNodeType type = n.getType();
			if(type == Exit || type == Entry) {
				for(int i = index; i < nodes.length; i++) {
					if(nodes[i].isInPcRange(n.getJumpPoint())) {
 						n.addChild(nodes[i]);<commit_msg>modify for omission of condition in case of StringSwitch.<commit_after>package sds.assemble.controlflow;

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.ArrayDeque;
import java.util.Deque;

import sds.assemble.MethodContent.ExceptionContent;
import sds.assemble.LineInstructions;

import static sds.assemble.controlflow.DominatorNodeSearcher.searchCommon;
import static sds.assemble.controlflow.CFNodeType.Entry;
import static sds.assemble.controlflow.CFNodeType.End;
import static sds.assemble.controlflow.CFNodeType.Exit;
import static sds.assemble.controlflow.CFNodeType.LoopEntry;
import static sds.assemble.controlflow.CFNodeType.LoopExit;
import static sds.assemble.controlflow.CFNodeType.StringSwitch;
import static sds.assemble.controlflow.CFNodeType.Switch;
import static sds.assemble.controlflow.CFEdgeType.JumpToCatch;
import static sds.assemble.controlflow.CFEdgeType.JumpToFinally;
import static sds.classfile.bytecode.MnemonicTable._goto;
import static sds.classfile.bytecode.MnemonicTable.goto_w;

/**
 * This builder class is for control flow graph.<br>
 * This class is designed singleton.
 * @author inagaki
 */
public class CFGBuilder {
	private static CFGBuilder builder = null;

	/**
	 * returns own instance.
	 * @return instance
	 */
	public static CFGBuilder getInstance() {
		if(builder == null) {
			builder = new CFGBuilder();
		}
		return builder;
	}

	/**
	 * returns control flow graph.
	 * @param inst method's instructions
	 * @param ex content of method's try-catch-finally
	 * @return control flow graph
	 */
	public CFNode[] build(LineInstructions[] inst, ExceptionContent ex) {
		/** 1. create nodes **/
		CFNode[] nodes = new CFNode[inst.length];
		for(int i = 0; i < nodes.length; i++) {
			nodes[i] = new CFNode(inst[i]);
		}
		
		/** 2. set parent and child, and investigate try-catch-finally **/
		int index = 0;
		for(CFNode n : nodes) {
			// processing for try-catch-finally
			boolean isGoto = (n.getStart().getOpcodeType() == _goto)
						  || (n.getStart().getOpcodeType() == goto_w);
			int[] tryIndex= ex.getIndexInRange(n.getStart().getPc(), false, isGoto);
			int[] catchTypeIndex = ex.getIndexInRange(n.getStart().getPc(), true, isGoto);
			if(tryIndex.length > 0) { // for catch
				n.inTry = true;
				for(int ti : tryIndex) {
					int catchIndex = ex.getTarget()[ti];
					for(int i = index; i < nodes.length; i++) {
						if(nodes[i].isInPcRange(catchIndex)) {
							nodes[i].isCatchEntry = true;
							n.addChild(nodes[i], JumpToCatch);
							nodes[i].addParent(n, JumpToCatch);
							break;
						}
					}
				}
			}
			if(catchTypeIndex.length > 0) { // for finally
				for(int ci : catchTypeIndex) {
					int finallyIndex = ex.getTarget()[ci];
					for(int i = index; i < nodes.length; i++) {
						if(nodes[i].isInPcRange(finallyIndex)) {
							nodes[i].isFinallyEntry = true;
							n.addChild(nodes[i], JumpToFinally);
							nodes[i].addParent(n, JumpToFinally);
							break;
						}
					}
				}
			}
			// processing for setting parent and child.
			if(index > 0) {
				CFNodeType type = nodes[index-1].getType();
				if(type != Exit && type != LoopExit && type != Switch
				&& type != End && type != StringSwitch) {
					n.addParent(nodes[index-1]);
					nodes[index-1].addChild(n);
				}
			} else if(index == nodes.length-1) {
				CFNodeType type = n.getType();
				if(type != Exit && type != LoopExit && type != Switch && type != StringSwitch) {
					n.addChild(nodes[index]);
					nodes[index].addParent(n);
				}
			}
			index++;
		}

		/** 3. set jump point node **/
		index = 0;
		for(CFNode n : nodes) {
			CFNodeType type = n.getType();
			if(type == Exit || type == Entry) {
				for(int i = index; i < nodes.length; i++) {
					if(nodes[i].isInPcRange(n.getJumpPoint())) {
 						n.addChild(nodes[i]);
{'fraction_non_alphanumeric': 0.1407870247274661, 'fraction_numerical': 0.0034565275192767883, 'mean_word_length': 3.425294117647059, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3104324', 'n_tokens_mistral': 3009, 'n_tokens_neox': 2526, 'n_words': 557}