<commit_before>package polyglot.visit;

import java.util.HashMap;
import java.util.Map;

import polyglot.ast.Node;
import polyglot.ast.NodeFactory;
import polyglot.frontend.Job;
import polyglot.types.SemanticException;
import polyglot.types.Type;
import polyglot.types.TypeSystem;
import polyglot.util.ErrorQueue;
import polyglot.util.InternalCompilerError;
import polyglot.util.Position;
import polyglot.util.SubtypeSet;

/** Visitor which checks if exceptions are caught or declared properly. */
public class ExceptionChecker extends ErrorHandlingVisitor
{
    protected ExceptionChecker outer;
    protected SubtypeSet scope;
    protected Map exceptionPositions;

    public ExceptionChecker(Job job, TypeSystem ts, NodeFactory nf) {
	super(job, ts, nf);
	this.outer = null;
        this.scope = new SubtypeSet(ts.Throwable());
        this.exceptionPositions = new HashMap();
    }

    public ExceptionChecker push() {
        ExceptionChecker ec = (ExceptionChecker) this.visitChildren();
        ec.outer = this;
        ec.scope = new SubtypeSet(ts.Throwable());
        ec.exceptionPositions = new HashMap();
        return ec;
    }

    public ExceptionChecker pop() {
        return outer;
    }

    /**
     * This method is called when we are to perform a "normal" traversal of 
     * a subtree rooted at <code>n</code>.   At every node, we will push a 
     * stack frame.  Each child node will add the exceptions that it throws
     * to this stack frame. For most nodes ( excdeption for the try / catch)
     * will just aggregate the stack frames.
     *
     * @param n The root of the subtree to be traversed.
     * @return The <code>NodeVisitor</code> which should be used to visit the 
     *  children of <code>n</code>.
     *
     */
    protected NodeVisitor enterCall(Node n) throws SemanticException {
	return n.exceptionCheckEnter(push());
    }

    protected NodeVisitor enterError(Node n) {
	return push();
    }

    /**
     * Here, we pop the stack frame that we pushed in enter and agregate the 
     * exceptions.
     *
     * @param old The original state of root of the current subtree.
     * @param n The current state of the root of the current subtree.
     * @param v The <code>NodeVisitor</code> object used to visit the children.
     * @return The final result of the traversal of the tree rooted at 
     *  <code>n</code>.
     */
    protected Node leaveCall(Node old, Node n, NodeVisitor v)
	throws SemanticException {
        
        ExceptionChecker inner = (ExceptionChecker) v;
        
        if (inner.outer != this) throw new InternalCompilerError("oops!");
        
        // gather exceptions from this node.
        n = n.del().exceptionCheck(inner);
        
        // Merge results from the children and free the checker used for the
        // children.
        SubtypeSet t = inner.throwsSet();
        throwsSet().addAll(t);
        exceptionPositions.putAll(inner.exceptionPositions);

	return n;
    }

    /**
     * The ast nodes will use this callback to notify us that they throw an 
     * exception of type t. This should only be called by MethodExpr node, 
     * and throw node, since they are the only node which can generate
     * exceptions.  
     *
     * @param t The type of exception that the node throws.
     */
    public void throwsException(Type t, Position pos) {
	throwsSet().add(t) ;
        exceptionPositions.put(t, pos);
    }
    
    /**
     * Method to allow the throws clause and method body to inspect and
     * modify the throwsSet.
     */
    public SubtypeSet throwsSet() {
        return (SubtypeSet) scope;
    }
    
    /**
     * Method to determine the position at which a particular exception is 
     * thrown
     */
    public Position exceptionPosition(Type t) {
        return (Position)exceptionPositions.get(t);
    }
}
<commit_msg>Lazily instantiate the SubtypeSet, to prevent Throwable from being loaded too early.<commit_after>package polyglot.visit;

import java.util.HashMap;
import java.util.Map;

import polyglot.ast.Node;
import polyglot.ast.NodeFactory;
import polyglot.frontend.Job;
import polyglot.types.*;
import polyglot.util.*;

/** Visitor which checks if exceptions are caught or declared properly. */
public class ExceptionChecker extends ErrorHandlingVisitor
{
    protected ExceptionChecker outer;
    private SubtypeSet scope = null; // lazily instantiated
    protected Map exceptionPositions;

    public ExceptionChecker(Job job, TypeSystem ts, NodeFactory nf) {
	super(job, ts, nf);
	this.outer = null;
        this.exceptionPositions = new HashMap();
    }

    public ExceptionChecker push() {
        ExceptionChecker ec = (ExceptionChecker) this.visitChildren();
        ec.outer = this;
        ec.exceptionPositions = new HashMap();
        return ec;
    }

    public ExceptionChecker pop() {
        return outer;
    }

    /**
     * This method is called when we are to perform a "normal" traversal of 
     * a subtree rooted at <code>n</code>.   At every node, we will push a 
     * stack frame.  Each child node will add the exceptions that it throws
     * to this stack frame. For most nodes ( excdeption for the try / catch)
     * will just aggregate the stack frames.
     *
     * @param n The root of the subtree to be traversed.
     * @return The <code>NodeVisitor</code> which should be used to visit the 
     *  children of <code>n</code>.
     *
     */
    protected NodeVisitor enterCall(Node n) throws SemanticException {
	return n.exceptionCheckEnter(push());
    }

    protected NodeVisitor enterError(Node n) {
	return push();
    }

    /**
     * Here, we pop the stack frame that we pushed in enter and agregate the 
     * exceptions.
     *
     * @param old The original state of root of the current subtree.
     * @param n The current state of the root of the current subtree.
     * @param v The <code>NodeVisitor</code> object used to visit the children.
     * @return The final result of the traversal of the tree rooted at 
     *  <code>n</code>.
     */
    protected Node leaveCall(Node old, Node n, NodeVisitor v)
	throws SemanticException {
        
        ExceptionChecker inner = (ExceptionChecker) v;
        
        if (inner.outer != this) throw new InternalCompilerError("oops!");
        
        // gather exceptions from this node.
        n = n.del().exceptionCheck(inner);
        
        // Merge results from the children and free the checker used for the
        // children.
        SubtypeSet t = inner.throwsSet();
        throwsSet().addAll(t);
        exceptionPositions.putAll(inner.exceptionPositions);

	return n;
    }

    /**
     * The ast nodes will use this callback to notify us that they throw an 
     * exception of type t. This should only be called by MethodExpr node, 
     * and throw node, since they are the only node which can generate
     * exceptions.  
     *
     * @param t The type of exception that the node throws.
     */
    public void throwsException(Type t, Position pos) {
	throwsSet().add(t) ;
        exceptionPositions.put(t, pos);
    }
    
    /**
     * Method to allow the throws clause and method body to inspect and
     * modify the throwsSet.
     */
    public SubtypeSet throwsSet() {
        if (scope == null) {
            scope = new SubtypeSet(ts.Throwable());
        }
        return scope;
    }
    
    /**
     * Method to determine the position at which a particular exception is 
     * thrown
     */
    public Position exceptionPosition(Type t) {
        return (Position)exceptionPositions.get(t);
    }
}

{'fraction_non_alphanumeric': 0.08379373848987108, 'fraction_numerical': 0.0, 'mean_word_length': 2.5728383458646618, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, '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': '4998988', 'n_tokens_mistral': 2092, 'n_tokens_neox': 2073, 'n_words': 777}