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

Source Code of com.google.gwt.core.ext.soyc.coderef.EntityRecorder

/*
* Copyright 2013 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.coderef;

import com.google.gwt.core.ext.linker.EmittedArtifact.Visibility;
import com.google.gwt.core.ext.linker.SyntheticArtifact;
import com.google.gwt.core.ext.soyc.SourceMapRecorder;
import com.google.gwt.core.ext.soyc.coderef.EntityDescriptor.Fragment;
import com.google.gwt.core.linker.SoycReportLinker;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.JsSourceMap;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JField;
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.JavaToJavaScriptMap;
import com.google.gwt.dev.jjs.impl.codesplitter.FragmentPartitioningResult;
import com.google.gwt.dev.js.SizeBreakdown;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import com.google.gwt.thirdparty.json.JSONArray;
import com.google.gwt.thirdparty.json.JSONException;
import com.google.gwt.thirdparty.json.JSONObject;
import com.google.gwt.util.tools.Utility;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
* Creates the entities artifacts for the new soyc.
*/
public class EntityRecorder {

  public static final String ENTITIES         = "entities";
  public static final String FRAGMENT_ID      = "id";
  public static final String FRAGMENT_SIZE    = "size";
  public static final String FRAGMENT_STR_VAR = "strAndVarSize";
  public static final String FRAGMENT_POINTS  = "runAsyncs";
  public static final String FRAGMENTS        = "fragments";
  public static final String INITIAL_SEQUENCE = "initialSequence";

  public static List<SyntheticArtifact> makeSoycArtifacts(int permutationId,
      List<JsSourceMap> sourceInfoMaps, String sourceMapFilePrefix, JavaToJavaScriptMap jjsmap,
      SizeBreakdown[] sizeBreakdowns, DependencyGraphRecorder codeGraph, JProgram jprogram) {

    List<SyntheticArtifact> artifacts = Lists.newArrayList();
    try {
      EntityRecorder recorder = new EntityRecorder(sizeBreakdowns, permutationId);
      recorder.recordCodeReferences(codeGraph, sizeBreakdowns, jjsmap);
      recorder.recordFragments(jprogram);
      artifacts.addAll(recorder.toReturn);
      artifacts.addAll(SourceMapRecorder.execWithJavaNames(permutationId, sourceInfoMaps,
          sourceMapFilePrefix));
    } catch (Exception e) {
      throw new InternalCompilerException(e.toString(), e);
    }

    return artifacts;
  }

  private final List<SyntheticArtifact> toReturn = Lists.newArrayList();
  private final int permutationId;
  private final int[] fragmentSizes;
  // String and variable sizes
  private final int[] otherSizes;
  private JSONObject[] sizeMetrics;

  private EntityRecorder(SizeBreakdown[] sizeBreakdowns, int permutationId) {
    fragmentSizes = new int[sizeBreakdowns.length];
    otherSizes = new int[sizeBreakdowns.length];
    for (int i = 0; i < sizeBreakdowns.length; i++) {
      fragmentSizes[i] = sizeBreakdowns[i].getSize();
      otherSizes[i] = 0;
    }
    this.permutationId = permutationId;
  }

  private JSONObject getSizeMetrics(int fragment) throws JSONException {
    JSONObject obj = new JSONObject();
    obj.put(FRAGMENT_ID, fragment);
    obj.put(FRAGMENT_SIZE, this.fragmentSizes[fragment]);
    obj.put(FRAGMENT_STR_VAR, this.otherSizes[fragment]);
    return obj;
  }

  private void recordCodeReferences(DependencyGraphRecorder codeGraph,
      SizeBreakdown[] sizeBreakdowns, JavaToJavaScriptMap jjsmap)
      throws IOException, JSONException {
    this.sizeMetrics = new JSONObject[sizeBreakdowns.length];
    // add sizes and other info
    for (int i = 0; i < sizeBreakdowns.length; i++) {
      for (Entry<JsName, Integer> kv : sizeBreakdowns[i].getSizeMap().entrySet()) {
        JsName name = kv.getKey();
        int size = kv.getValue();
        // find method
        JMethod method = jjsmap.nameToMethod(name);
        if (method != null) {
          codeGraph.methodDescriptorFrom(method).addFragment(new Fragment(i, size));
          continue;
        }
        // find field
        JField field = jjsmap.nameToField(name);
        if ((field != null) && (field.getEnclosingType() != null)) {
          codeGraph.classDescriptorFrom(field.getEnclosingType()).fieldFrom(field)
              .addFragment(new Fragment(i, size));
          continue;
        }
        // find class
        JClassType type = jjsmap.nameToType(name);
        if (type != null) {
          codeGraph.classDescriptorFrom(type).addFragment(new Fragment(i, size));
          continue;
        }
        // otherwise is a string or variable
        this.otherSizes[i] += size;
      }
      sizeMetrics[i] = this.getSizeMetrics(i);
    }
    // adding symbol names considering that jjsmap has all obfuscated name for all entities
    for (ClassDescriptor cls : codeGraph.getCodeModel().values()) {
      JDeclaredType type = cls.getTypeReference();
      if (type instanceof JClassType) {
        JsName jsName = jjsmap.nameForType((JClassType) type);
        if (jsName != null) {
          cls.addObfuscatedName(jsName.getShortIdent());
        }
      }
      for (MethodDescriptor mth : cls.getMethods()) {
        for (JMethod jMethod : mth.getMethodReferences()) {
          JsName jsName = jjsmap.nameForMethod(jMethod);
          if (jsName != null) {
            mth.addObfuscatedName(jsName.getShortIdent());
          }
        }
      }
      for (JField field : type.getFields()) {
        JsName jsName = jjsmap.nameForField(field);
        if (jsName != null) {
          cls.fieldFrom(field).addObfuscatedName(jsName.getShortIdent());
        }
      }
    }
    // build json
    addArtifactFromJson(
        EntityDescriptorJsonTranslator.writeJson(
            PackageDescriptor.from(codeGraph.getCodeModel())),
            ENTITIES + permutationId + ".json");
  }

  private String addArtifactFromJson(Object value, String named) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PrintWriter writer = new PrintWriter(baos);
    writer.write(value.toString());
    Utility.close(writer);

    // TODO(ocallau) Must be updated with the correct/final linker
    SyntheticArtifact artifact = new SyntheticArtifact(
        SoycReportLinker.class, named, baos.toByteArray());
    artifact.setVisibility(Visibility.LegacyDeploy);

    toReturn.add(artifact);
    return named;
  }

  private void recordFragments(JProgram jprogram) throws IOException, JSONException {
    JSONObject jsonPoints = new JSONObject();
    // adding runAsyncs, if any
    FragmentPartitioningResult partitionResult = jprogram.getFragmentPartitioningResult();
    // a FragmentPartitioningResult' instance exist if and only if there are runAyncs nodes
    if (partitionResult != null) {
      Map<Integer, Set<String>> runAsyncPerFragment = Maps.newHashMap();
      for (JRunAsync runAsync : jprogram.getRunAsyncs()) {
        int fragmentId = partitionResult.getFragmentForRunAsync(runAsync.getRunAsyncId());
        Set<String> runAsyncNames = runAsyncPerFragment.get(fragmentId);
        if (runAsyncNames == null) {
          runAsyncNames = Sets.newHashSet();
        }
        runAsyncNames.add(runAsync.getName());
        runAsyncPerFragment.put(fragmentId, runAsyncNames);
      }
      for (Integer idx : runAsyncPerFragment.keySet()) {
        sizeMetrics[idx].put(FRAGMENT_POINTS, runAsyncPerFragment.get(idx));
      }
      // initial fragment sequence points
      JSONArray initialSequence = new JSONArray();
      for (int fragId : jprogram.getInitialFragmentIdSequence()) {
        initialSequence.put(partitionResult.getFragmentForRunAsync(fragId));
      }
      jsonPoints.put(INITIAL_SEQUENCE, initialSequence);
    }

    jsonPoints.put(FRAGMENTS, this.sizeMetrics);
    addArtifactFromJson(jsonPoints, FRAGMENTS + permutationId + ".json");
  }
}
TOP

Related Classes of com.google.gwt.core.ext.soyc.coderef.EntityRecorder

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.