blob: bbf20213323196580f53c5615bccd34197a8d5df [file] [log] [blame]
/*
* 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.linker;
import com.google.gwt.core.ext.Linker;
import com.google.gwt.core.ext.LinkerContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.linker.Artifact;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.CompilationResult;
import com.google.gwt.core.ext.linker.EmittedArtifact;
import com.google.gwt.core.ext.linker.EmittedArtifact.Visibility;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.LinkerOrder.Order;
import com.google.gwt.core.ext.linker.ModuleMetricsArtifact;
import com.google.gwt.core.ext.linker.SelectionProperty;
import com.google.gwt.core.ext.linker.Shardable;
import com.google.gwt.core.ext.linker.SyntheticArtifact;
import com.google.gwt.core.ext.linker.Transferable;
import com.google.gwt.soyc.CompilerMetricsXmlFormatter;
import com.google.gwt.soyc.SoycDashboard;
import com.google.gwt.soyc.io.ArtifactsOutputDirectory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
* Converts SOYC report files into emitted private artifacts.
*/
@LinkerOrder(Order.POST)
@Shardable
public class SoycReportLinker extends Linker {
/**
* An artifact giving a one-line description of a permutation ID in terms of
* its deferred bindings.
*/
@Transferable
private static class PermDescriptionArtifact extends
Artifact<PermDescriptionArtifact> {
private List<String> permDesc;
private int permId;
public PermDescriptionArtifact(int permId, List<String> permDesc) {
super(SoycReportLinker.class);
this.permId = permId;
this.permDesc = permDesc;
}
public List<String> getPermDesc() {
return permDesc;
}
public int getPermId() {
return permId;
}
@Override
public int hashCode() {
return permId;
}
@Override
protected int compareToComparableArtifact(PermDescriptionArtifact o) {
int cmp;
cmp = permId - o.getPermId();
if (cmp != 0) {
return cmp;
}
cmp = permDesc.size() - o.getPermDesc().size();
if (cmp != 0) {
return cmp;
}
for (int i = 0; i < permDesc.size(); i++) {
cmp = permDesc.get(i).compareTo(o.getPermDesc().get(i));
if (cmp != 0) {
return cmp;
}
}
return 0;
}
@Override
protected Class<PermDescriptionArtifact> getComparableArtifactType() {
return PermDescriptionArtifact.class;
}
}
@Override
public String getDescription() {
return "Emit compile report artifacts";
}
@Override
public ArtifactSet link(TreeLogger logger, LinkerContext context,
ArtifactSet artifacts, boolean onePermutation) {
boolean reportFilesPresent = anyReportFilesPresent(artifacts);
boolean metricsPresent = anyCompilerMetricsPresent(artifacts);
if (!reportFilesPresent && !metricsPresent) {
return artifacts;
}
artifacts = new ArtifactSet(artifacts);
if (!onePermutation) {
buildCompilerMetricsXml(artifacts);
}
if (reportFilesPresent) {
if (onePermutation) {
emitPermutationDescriptions(artifacts);
} else {
buildTopLevelFiles(logger, artifacts);
}
}
return artifacts;
}
/**
* Check whether an artifact set contains any compilerMetrics.
*/
boolean anyCompilerMetricsPresent(ArtifactSet artifacts) {
return !artifacts.find(ModuleMetricsArtifact.class).isEmpty();
}
/**
* Check whether an artifact set contains any SOYC report documents.
*/
boolean anyReportFilesPresent(ArtifactSet artifacts) {
String prefix1 = ArtifactsOutputDirectory.COMPILE_REPORT_DIRECTORY + "/";
String prefix2 = "soycReport/" + prefix1;
for (EmittedArtifact art : artifacts.find(EmittedArtifact.class)) {
if (art.getPartialPath().startsWith(prefix1)) {
return true;
}
if (art.getPartialPath().startsWith(prefix2)) {
return true;
}
}
return false;
}
/**
* Compiler Metrics are captured in the module load, precompilation,
* and compile permutations step, then all merged together into a single
* XML file as output. That file can then be consumed by external
* reporting tools.
*/
private void buildCompilerMetricsXml(ArtifactSet artifacts) {
ModuleMetricsArtifact moduleMetrics = null;
Set<ModuleMetricsArtifact> moduleMetricsSet = artifacts.find(
ModuleMetricsArtifact.class);
if (!moduleMetricsSet.isEmpty()) {
for (ModuleMetricsArtifact metrics : moduleMetricsSet) {
moduleMetrics = metrics;
// We only need one module metrics definition.
break;
}
}
// No module metrics? Then we'll skip creating the compilerMetrics output
if (moduleMetrics == null) {
return;
}
byte[] xmlResult = CompilerMetricsXmlFormatter.writeMetricsAsXml(
artifacts, moduleMetrics);
EmittedArtifact metricsArtifact = new SyntheticArtifact(
SoycReportLinker.class, "compilerMetrics.xml", xmlResult);
metricsArtifact.setVisibility(Visibility.Private);
artifacts.add(metricsArtifact);
}
private void buildTopLevelFiles(TreeLogger logger,
ArtifactSet artifacts) {
ArtifactsOutputDirectory out = new ArtifactsOutputDirectory();
try {
new SoycDashboard(out).generateCrossPermutationFiles(
extractPermutationDescriptions(artifacts));
} catch (IOException e) {
logger.log(TreeLogger.ERROR,
"Error while generating a Story of Your Compile", e);
e.printStackTrace();
}
artifacts.addAll(out.getArtifacts());
}
private void emitPermutationDescriptions(ArtifactSet artifacts) {
for (CompilationResult res : artifacts.find(CompilationResult.class)) {
int permId = res.getPermutationId();
List<String> permDesc = new ArrayList<String>();
for (Map<SelectionProperty, String> propertyMap : res.getPropertyMap()) {
permDesc.add(SymbolMapsLinker.propertyMapToString(propertyMap));
}
artifacts.add(new PermDescriptionArtifact(permId, permDesc));
}
}
private Map<String, List<String>> extractPermutationDescriptions(
ArtifactSet artifacts) {
Map<String, List<String>> permDescriptions = new TreeMap<String,
List<String>>();
for (PermDescriptionArtifact art : artifacts.find(
PermDescriptionArtifact.class)) {
permDescriptions.put(Integer.toString(art.getPermId()),
art.getPermDesc());
}
return permDescriptions;
}
}