Package com.google.gwt.core.ext.soyc.impl

Source Code of com.google.gwt.core.ext.soyc.impl.DependencyRecorder

/*
* Copyright 2009 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.core.ext.soyc.impl;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.impl.ControlFlowAnalyzer;
import com.google.gwt.dev.jjs.impl.CodeSplitter.MultipleDependencyGraphRecorder;
import com.google.gwt.util.tools.Utility;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.zip.GZIPOutputStream;

/**
* The control-flow dependency recorder for Compile Report.
*/
public class DependencyRecorder implements MultipleDependencyGraphRecorder {
  /**
   * DependencyRecorder is not allowed to throw checked exceptions, because if
   * it did then {@link com.google.gwt.dev.jjs.impl.CodeSplitter} and {@link ControlFlowAnalyzer} would
   * throw exceptions all over the place. Instead, this class throws
   * NestedIOExceptions that wrap them.
   */
  public static class NestedIOException extends RuntimeException {
    public NestedIOException(IOException e) {
      super(e);
    }
  }

  private final StringBuilder builder = new StringBuilder();
  private final OutputStream finalOutput;
  private OutputStreamWriter writer;

  public DependencyRecorder(OutputStream out) {
    this.finalOutput = out;
  }

  public void close() {
    printPost();
    flushOutput();
    try {
      writer.close();
    } catch (IOException e) {
      throw new NestedIOException(e);
    }
  }

  public void endDependencyGraph() {
    builder.append("</table>");
    flushOutput();
  }

  /**
   * Used to record the dependencies of a specific method.
   */
  public void methodIsLiveBecause(JMethod liveMethod,
      ArrayList<JMethod> dependencyChain) {
    printMethodDependency(dependencyChain);
  }

  public void open() {
    try {
      this.writer = new OutputStreamWriter(new GZIPOutputStream(finalOutput),
          "UTF-8");
    } catch (UnsupportedEncodingException e) {
      throw new InternalCompilerException("UTF-8 is an unsupported encoding", e);
    } catch (IOException e) {
      throw new NestedIOException(e);
    }

    printPre();
  }

  public void startDependencyGraph(String identifier, String extnds) {
    builder.append("<table name=\"");
    builder.append(identifier);
    builder.append("\"");
    if (extnds != null) {
      builder.append(" extends=\"");
      builder.append(extnds);
      builder.append("\"");
    }
    builder.append(">\n");
  }

  /**
   * Used to record dependencies of a program.
   */
  protected void recordDependenciesImpl(TreeLogger logger, JProgram jprogram) {

    logger = logger.branch(TreeLogger.DEBUG,
        "Creating dependencies file for the compile report");

    ControlFlowAnalyzer dependencyAnalyzer = new ControlFlowAnalyzer(jprogram);
    dependencyAnalyzer.setDependencyRecorder(this);

    try {
      printPre();
      for (JMethod method : jprogram.getAllEntryMethods()) {
        dependencyAnalyzer.traverseFrom(method);
        maybeFlushOutput();
      }
      printPost();

      writer.write(builder.toString());
      Utility.close(writer);

    } catch (Throwable e) {
      logger.log(TreeLogger.ERROR, "Could not write dependency file.", e);
    }
  }

  private void flushOutput() {
    try {
      writer.write(builder.toString());
    } catch (IOException e) {
      throw new NestedIOException(e);
    }
    builder.setLength(0);
  }

  private void maybeFlushOutput() {
    if (builder.length() > 8 * 1024) {
      flushOutput();
    }
  }

  /**
   * Records one dependency chain to a file. More specifically, it records the
   * last link of the dependency chain. The full dependency chain can be
   * recovered by code that reads the entire dependencies file, because it can
   * do repeated lookups into the dependencies table to follow the chain.
   */
  private void printMethodDependency(ArrayList<JMethod> dependencyChain) {
    int size = dependencyChain.size();
    if (size < 2) {
      return;
    }

    JMethod curMethod = dependencyChain.get(size - 1);
    builder.append("<method name=\"");
    if (curMethod.getEnclosingType() != null) {
      builder.append(curMethod.getEnclosingType().getName());
      builder.append("::");
    }
    builder.append(curMethod.getName());
    builder.append("\">\n");

    JMethod depMethod = dependencyChain.get(size - 2);
    builder.append("<called by=\"");
    if (depMethod.getEnclosingType() != null) {
      builder.append(depMethod.getEnclosingType().getName());
      builder.append("::");
    }
    builder.append(depMethod.getName());
    builder.append("\"/>\n");
    builder.append("</method>\n");
  }

  /**
   * Prints the closing lines necessary for the dependencies file.
   */
  private void printPost() {
    builder.append("</soyc-dependencies>\n");
  }

  /**
   * Prints the preamble necessary for the dependencies file.
   */
  private void printPre() {
    builder.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<soyc-dependencies>\n");
  }
}
TOP

Related Classes of com.google.gwt.core.ext.soyc.impl.DependencyRecorder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.