com.google.gwt.dev.jjs.InternalCompilerException.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.dev.jjs.InternalCompilerException.java

Source

/*
 * Copyright 2007 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.jjs;

import java.util.ArrayList;
import java.util.List;

/**
 * Indicates the compiler encountered an unexpected and unsupported state of
 * operation.
 */
public class InternalCompilerException extends RuntimeException {

    /**
     * Information regarding a node that was being processed when an
     * InternalCompilerException was thrown.
     */
    public static final class NodeInfo {

        static void preload() {
            // Initialize this class on static invocation.
        }

        private final String className;
        private final String description;
        private final SourceInfo sourceInfo;

        NodeInfo(String className, String description, SourceInfo sourceInfo) {
            this.className = className;
            this.description = description;
            this.sourceInfo = sourceInfo;
        }

        /**
         * Returns the name of the Java class of the node.
         */
        public String getClassName() {
            return className;
        }

        /**
         * Returns a text description of the node; typically toString().
         */
        public String getDescription() {
            return description;
        }

        /**
         * Returns the node's source info, if available; otherwise {@code null}.
         */
        public SourceInfo getSourceInfo() {
            return sourceInfo;
        }
    }

    /**
     * Tracks if there's a pending addNode() to avoid recursion sickness.
     */
    private static final ThreadLocal<InternalCompilerException> pendingICE = new ThreadLocal<InternalCompilerException>();

    /**
     * Force this class to be preloaded. If we don't preload this class, we can
     * get into bad behavior if we later try to load this class under out of
     * memory or out of stack conditions.
     */
    public static void preload() {
        // Initialize this class on static invocation.
        NodeInfo.preload();
        pendingICE.set(pendingICE.get());
    }

    private final List<NodeInfo> nodeTrace = new ArrayList<NodeInfo>();

    /**
     * Constructs a new exception with the specified node, message, and cause.
     */
    public InternalCompilerException(HasSourceInfo node, String message, Throwable cause) {
        this(message, cause);
        addNode(node);
    }

    /**
     * Constructs a new exception with the specified message.
     */
    public InternalCompilerException(String message) {
        super(message);
    }

    /**
     * Constructs a new exception with the specified message and cause.
     */
    public InternalCompilerException(String message, Throwable cause) {
        super(message, cause);
    }

    /**
     * Adds a node to the end of the node trace. This is similar to how a stack
     * trace works.
     */
    public void addNode(HasSourceInfo node) {
        InternalCompilerException other = pendingICE.get();
        if (other != null) {
            // Avoiding recursion sickness: Yet Another ICE must have occurred while
            // generating info for a prior ICE. Just bail!
            return;
        }

        String className = null;
        String description = null;
        SourceInfo sourceInfo = null;
        try {
            pendingICE.set(this);
            className = node.getClass().getName();
            sourceInfo = node.getSourceInfo();
            description = node.toString();
        } catch (Throwable e) {
            // ignore any exceptions
            if (description == null) {
                description = "<source info not available>";
            }
        } finally {
            pendingICE.set(null);
        }
        addNode(className, description, sourceInfo);
    }

    /**
     * Adds information about a a node to the end of the node trace. This is
     * similar to how a stack trace works.
     */
    public void addNode(String className, String description, SourceInfo sourceInfo) {
        nodeTrace.add(new NodeInfo(className, description, sourceInfo));
    }

    /**
     * Returns a list of nodes that were being processed when this exception was
     * thrown. The list reflects the parent-child relationships of the AST and is
     * is in order from children to parents. The first element of the returned
     * list is the node that was most specifically being visited when the
     * exception was thrown.
     */
    public List<NodeInfo> getNodeTrace() {
        return nodeTrace;
    }

}