blob: 728d869baff1aec4de0e14def4e7a9194ba02cd7 [file] [log] [blame]
/*
* 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();
}
}
}