| /* |
| * 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.js; |
| |
| import com.google.gwt.core.ext.BadPropertyValueException; |
| import com.google.gwt.core.ext.ConfigurationProperty; |
| import com.google.gwt.core.ext.PropertyOracle; |
| import com.google.gwt.dev.jjs.InternalCompilerException; |
| import com.google.gwt.dev.js.ast.JsContext; |
| import com.google.gwt.dev.js.ast.JsModVisitor; |
| import com.google.gwt.dev.js.ast.JsProgram; |
| import com.google.gwt.dev.js.ast.JsVars; |
| import com.google.gwt.dev.js.ast.JsVars.JsVar; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * Divides large var statements into smaller ones. Very long var statements have |
| * trouble on some browsers, including the initial Safari 4 beta. See Issue |
| * 3455. |
| */ |
| public class JsBreakUpLargeVarStatements extends JsModVisitor { |
| private static final String CONFIG_PROP_MAX_VARS = "compiler.max.vars.per.var"; |
| |
| public static void exec(JsProgram program, PropertyOracle[] propertyOracles) { |
| (new JsBreakUpLargeVarStatements(propertyOracles)).accept(program); |
| } |
| |
| private static JsVars last(List<JsVars> list) { |
| return list.get(list.size() - 1); |
| } |
| |
| private final int maxVarsPerStatement; |
| |
| private JsBreakUpLargeVarStatements(PropertyOracle[] propertyOracles) { |
| maxVarsPerStatement = getMaxVarsPerStatement(propertyOracles[0]); |
| } |
| |
| @Override |
| public void endVisit(JsVars x, JsContext context) { |
| if (maxVarsPerStatement < 0) { |
| return; |
| } |
| |
| if (x.getNumVars() > maxVarsPerStatement) { |
| // compute a list of smaller JsVars statements |
| List<JsVars> smallerVars = new ArrayList<JsVars>(); |
| smallerVars.add(makeNewChildVars(x)); |
| |
| for (JsVar var : x) { |
| if (last(smallerVars).getNumVars() >= maxVarsPerStatement) { |
| // Previous statement is full; start a new one |
| smallerVars.add(makeNewChildVars(x)); |
| } |
| last(smallerVars).add(var); |
| } |
| |
| // replace x by the sequence smallerVars |
| for (JsVars sv : smallerVars) { |
| context.insertBefore(sv); |
| } |
| context.removeMe(); |
| } |
| } |
| |
| /** |
| * Look up in the specified property oracle the maximum number of variables to |
| * allow per var statement. |
| */ |
| private int getMaxVarsPerStatement(PropertyOracle propertyOracle) |
| throws InternalCompilerException, NumberFormatException { |
| ConfigurationProperty prop; |
| try { |
| prop = propertyOracle.getConfigurationProperty(CONFIG_PROP_MAX_VARS); |
| } catch (BadPropertyValueException e) { |
| throw new InternalCompilerException("Could not find property " |
| + CONFIG_PROP_MAX_VARS, e); |
| } |
| int t = Integer.parseInt(prop.getValues().get(0)); |
| return t; |
| } |
| |
| /** |
| * Make a new, empty {@link JsVars} that is a child of x. |
| */ |
| private JsVars makeNewChildVars(JsVars x) { |
| return new JsVars(x.getSourceInfo()); |
| } |
| } |