All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.core.ext.soyc.impl.DependencyRecorder Maven / Gradle / Ivy

Go to download

Vaadin is a web application framework for Rich Internet Applications (RIA). Vaadin enables easy development and maintenance of fast and secure rich web applications with a stunning look and feel and a wide browser support. It features a server-side architecture with the majority of the logic running on the server. Ajax technology is used at the browser-side to ensure a rich and interactive user experience.

There is a newer version: 8.25.2
Show newest version
/*
 * 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.ast.JRunAsync;
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.List;
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.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;
  }

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

  @Override
  public void endDependencyGraph() {
    builder.append("");
    flushOutput();
  }

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

  @Override
  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();
  }

  @Override
  public void startDependencyGraph(String identifier, String extnds) {
    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.getEntryMethods()) {
        dependencyAnalyzer.traverseFrom(method);
        maybeFlushOutput();
      }
      for (JRunAsync runAsync : jprogram.getRunAsyncs()) {
        dependencyAnalyzer.traverseFromRunAsync(runAsync);
        maybeFlushOutput();
      }
      printPost();

      flushOutput();
      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(List dependencyChain) {
    int size = dependencyChain.size();
    if (size < 2) {
      return;
    }

    printMethodDependencyBetween(dependencyChain.get(size - 1), dependencyChain.get(size - 2));
  }

  protected void printMethodDependencyBetween(JMethod curMethod, JMethod depMethod) {
    builder.append("\n");

    builder.append("\n");
    builder.append("\n");
  }

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

  /**
   * Prints the preamble necessary for the dependencies file.
   */
  private void printPre() {
    builder.append("\n\n");
  }
}