/* * 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.dev.jjs.impl; import com.google.gwt.core.ext.linker.StatementRanges; import com.google.gwt.core.ext.linker.impl.StandardStatementRanges; import com.google.gwt.core.ext.soyc.Range; import com.google.gwt.dev.jjs.SourceInfo; import java.util.ArrayList; import java.util.Map; /** * Base class for transforming program text. */ public abstract class JsAbstractTextTransformer { protected String js; protected StatementRanges originalStatementRanges; protected StatementRanges statementRanges; protected Map<Range, SourceInfo> sourceInfoMap; public JsAbstractTextTransformer(JsAbstractTextTransformer xformer) { this(xformer.getJs(), xformer.getStatementRanges(), xformer.getSourceInfoMap()); } public JsAbstractTextTransformer(String js, StatementRanges statementRanges, Map<Range, SourceInfo> sourceInfoMap) { this.js = js; this.statementRanges = statementRanges; this.originalStatementRanges = statementRanges; this.sourceInfoMap = sourceInfoMap; } public abstract void exec(); public String getJs() { return js; } public Map<Range, SourceInfo> getSourceInfoMap() { return sourceInfoMap; } public StatementRanges getStatementRanges() { return statementRanges; } protected void addStatement(int index, String code, StringBuilder newJs, ArrayList<Integer> starts, ArrayList<Integer> ends) { beginStatement(index, newJs, starts); newJs.append(code); endStatement(index, newJs, ends); } protected void beginStatement(int index, StringBuilder newJs, ArrayList<Integer> starts) { starts.add(newJs.length()); } /** * Called if any operations need to be performed before all statements have * been processed. * * @param newJs * @param starts * @param ends */ protected void beginStatements(StringBuilder newJs, ArrayList<Integer> starts, ArrayList<Integer> ends) { } protected void endStatement(int index, StringBuilder newJs, ArrayList<Integer> ends) { ends.add(newJs.length()); } /** * Called if any operations need to be performed after all statements have * been processed. * * @param newJs * @param starts * @param ends */ protected void endStatements(StringBuilder newJs, ArrayList<Integer> starts, ArrayList<Integer> ends) { } protected String getJsForRange(int stmtIndex) { return js.substring(statementRanges.start(stmtIndex), statementRanges.end(stmtIndex)); } /** * Dump functions and fragments back into a new JS string, and calculate a new * StatementRanges object. */ protected void recomputeJsAndStatementRanges(int[] stmtIndices) { StringBuilder newJs = new StringBuilder(); ArrayList<Integer> starts = new ArrayList<Integer>(); ArrayList<Integer> ends = new ArrayList<Integer>(); beginStatements(newJs, starts, ends); for (int stmtIndex : stmtIndices) { String code = getJsForRange(stmtIndex); addStatement(stmtIndex, code, newJs, starts, ends); } endStatements(newJs, starts, ends); assert starts.size() == ends.size() : "Size mismatch between start and" + " end statement ranges."; assert starts.get(0) == 0 && ends.get(ends.size() - 1) == newJs.length() : "statement ranges don't cover entire JS output string."; js = newJs.toString(); statementRanges = new StandardStatementRanges(starts, ends); updateSourceInfoMap(); } /** * Update the expression ranges in the SourceInfo map after the * transformer has manipulated the statements. */ protected abstract void updateSourceInfoMap(); }