/* * Copyright 2011 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; import com.google.gwt.core.ext.linker.SyntheticArtifact; import com.google.gwt.core.linker.SymbolMapsLinker; import com.google.gwt.dev.jjs.InternalCompilerException; import com.google.gwt.dev.jjs.SourceInfo; import com.google.gwt.thirdparty.debugging.sourcemap.FilePosition; import com.google.gwt.thirdparty.debugging.sourcemap.SourceMapFormat; import com.google.gwt.thirdparty.debugging.sourcemap.SourceMapGenerator; import com.google.gwt.thirdparty.debugging.sourcemap.SourceMapGeneratorFactory; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; /** * Creates Closure Compatible SourceMaps. */ public class SourceMapRecorder { public static List<SyntheticArtifact> makeSourceMapArtifacts( List<Map<Range, SourceInfo>> sourceInfoMaps, int permutationId) { List<SyntheticArtifact> toReturn = new ArrayList<SyntheticArtifact>(); recordSourceMap(sourceInfoMaps, toReturn, permutationId); return toReturn; } public static void recordSourceMap(List<Map<Range, SourceInfo>> sourceInfoMaps, List<SyntheticArtifact> artifacts, int permutationId) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); SourceMapGenerator generator = SourceMapGeneratorFactory.getInstance(SourceMapFormat.V3); OutputStreamWriter out = new OutputStreamWriter(baos); int fragment = 0; if (!sourceInfoMaps.isEmpty()) { for (Map<Range, SourceInfo> sourceMap : sourceInfoMaps) { generator.reset(); Set<Range> rangeSet = sourceMap.keySet(); Range[] ranges = rangeSet.toArray(new Range[rangeSet.size()]); Arrays.sort(ranges, Range.DEPENDENCY_ORDER_COMPARATOR); for (Range r : ranges) { SourceInfo si = sourceMap.get(r); if (si.getFileName() == null || si.getStartLine() < 0) { // skip over synthetics with no Java source continue; } if (r.getStartLine() == 0 || r.getEndLine() == 0) { // or other bogus entries that appear continue; } // Starting with V3, SourceMap line numbers are zero-based. // GWT's line numbers for Java files originally came from the JDT, which is 1-based, // so adjust them here to avoid an off-by-one error in debuggers. generator.addMapping(si.getFileName(), null, new FilePosition(si.getStartLine() - 1, 0), new FilePosition(r.getStartLine(), r.getStartColumn()), new FilePosition(r.getEndLine(), r.getEndColumn())); } try { baos.reset(); generator.appendTo(out, "sourceMap" + fragment); out.flush(); artifacts.add(new SymbolMapsLinker.SourceMapArtifact(permutationId, fragment, baos.toByteArray())); fragment++; } catch (IOException e) { throw new InternalCompilerException(e.toString(), e); } } } } }