| /* |
| * Copyright 2014 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.linker.impl; |
| |
| import com.google.gwt.core.ext.soyc.Range; |
| import com.google.gwt.dev.jjs.JsSourceMap; |
| import com.google.gwt.thirdparty.guava.common.collect.Lists; |
| |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| /** |
| * An efficient JS source map chunk extractor. |
| * <p> |
| * Efficient extraction comes with the restriction that extracted ranges must be consecutive to |
| * avoid having to seek within the subject JS source map data. |
| */ |
| public class JsSourceMapExtractor { |
| |
| private int lastTypeEndPosition; |
| private LinkedList<Range> ranges = Lists.newLinkedList(); |
| |
| public JsSourceMapExtractor(List<Range> ranges) { |
| this.ranges.addAll(ranges); |
| } |
| |
| public JsSourceMap extract(int typeStartPosition, int typeEndPosition, int typeStartLineNumber, |
| int typeEndLineNumber) { |
| assert !ranges.isEmpty() : "Source mappings can't be extracted past the end."; |
| skipTo(typeStartPosition); |
| |
| lastTypeEndPosition = typeEndPosition; |
| |
| List<Range> extractedRanges = Lists.newArrayList(); |
| |
| while (!ranges.isEmpty()) { |
| Range range = ranges.getFirst(); |
| if (range.getStart() < typeStartPosition || range.getStart() >= typeEndPosition) { |
| break; |
| } |
| if (range.getEnd() <= typeStartPosition || range.getEnd() > typeEndPosition) { |
| break; |
| } |
| |
| ranges.removeFirst(); |
| |
| // Normalize range position relative to the beginning of the type that contains it. |
| Range typeOffsetNormalizedRange = |
| range.createNormalizedCopy(typeStartPosition, typeStartLineNumber); |
| extractedRanges.add(typeOffsetNormalizedRange); |
| } |
| |
| int typeBytes = typeEndPosition - typeStartPosition; |
| int typeLines = typeEndLineNumber - typeStartLineNumber; |
| return new JsSourceMap(extractedRanges, typeBytes, typeLines); |
| } |
| |
| private void skipTo(int rangeEndPosition) { |
| assert lastTypeEndPosition <= rangeEndPosition : "You can only skip forward."; |
| |
| while (!ranges.isEmpty()) { |
| Range range = ranges.getFirst(); |
| |
| if (range.getStart() >= rangeEndPosition) { |
| break; |
| } |
| if (range.getEnd() > rangeEndPosition) { |
| break; |
| } |
| |
| ranges.removeFirst(); |
| } |
| } |
| } |