blob: 6a2532dd37c5a6482939d70bbbd2da563d922f0a [file] [log] [blame]
/*
* Copyright 2010 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.LinkerContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.CompilationResult;
import com.google.gwt.core.ext.linker.ConfigurationProperty;
import com.google.gwt.core.ext.linker.SelectionProperty;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.jjs.JsOutputOption;
import java.util.Map.Entry;
import java.util.SortedSet;
/**
* A utility class to fill in the properties javascript in linker templates.
*/
public class PropertiesUtil {
public static String addKnownPropertiesJs(TreeLogger logger,
CompilationResult result) {
StringBuilder propertiesJs = new StringBuilder();
// Multiple values for a property can result in one permutation. For
// example, this permutation may be valid for safari and chrome. However,
// we need to pick one, since the computePropValue() needs to return a
// single value. It actually doesn't matter which one we pick. The fact
// that safari and chrome compiled into one permutation indicates that
// for this module, the behavior is the same. Therefore, we just pick
// the first one.
for (Entry<SelectionProperty, String> entry :
result.getPropertyMap().first().entrySet()) {
propertiesJs.append("properties['");
propertiesJs.append(entry.getKey().getName());
propertiesJs.append("'] = '");
propertiesJs.append(entry.getValue());
propertiesJs.append("';");
}
return propertiesJs.toString();
}
public static StringBuffer addPropertiesJs(StringBuffer selectionScript,
TreeLogger logger, LinkerContext context)
throws UnableToCompleteException {
int startPos;
// Add property providers
startPos = selectionScript.indexOf("// __PROPERTIES_END__");
if (startPos == -1) {
return selectionScript;
}
selectionScript.insert(startPos, generatePropertyProviders(logger, context));
return selectionScript;
}
/**
* Returns JavaScript that declares and initializes the "providers" and "values" variables.
*
* <p>Requires $doc and $wnd variables to be defined. (And possibly others; this is unclear.)
*
* <p>Provides "providers" and "values" variables.</p>.
*
* <ul>
* <li>"providers" is a mapping from each binding property (string) to a no-argument function
* that determines its value.</li>
* <li>"values" is a mapping from each binding property (string) to the set of allowed values
* (represented as a mapping with the value as key).
* </li>
* </ul>
*/
public static String generatePropertiesSnippet(ModuleDef module, TreeLogger compileLogger)
throws UnableToCompleteException {
// TODO: PropertyProviderGenerator should specify the JavaScript environment that a
// property provider can assume so the caller of this function knows what it should provide.
LinkerContext linkerContext = new StandardLinkerContext(compileLogger, module,
module.getPublicResourceOracle(), JsOutputOption.PRETTY);
String initProvidersJs =
generatePropertyProviders(compileLogger, linkerContext);
return "var providers = {};\nvar values = {};\n" + initProvidersJs + "\n";
}
/**
* Generates JavaScript to create a property provider for each non-derived binding property
* in the given linker. The JavaScript mutates the "providers" and "values" variables which
* must already exist.
*/
private static String generatePropertyProviders(TreeLogger logger, LinkerContext context)
throws UnableToCompleteException {
StringBuilder out = new StringBuilder();
for (SelectionProperty p : context.getProperties()) {
out.append(generatePropertyProvider(logger, p, context.getConfigurationProperties()));
}
return out.toString();
}
private static String generatePropertyProvider(TreeLogger logger,
SelectionProperty prop, SortedSet<ConfigurationProperty> configurationProperties)
throws UnableToCompleteException {
StringBuilder toReturn = new StringBuilder();
if (prop.tryGetValue() == null && !prop.isDerived()) {
toReturn.append("providers['" + prop.getName() + "'] = function()");
toReturn.append(prop.getPropertyProvider(logger, configurationProperties));
toReturn.append(";");
toReturn.append("values['" + prop.getName() + "'] = {");
boolean needsComma = false;
int counter = 0;
for (String value : prop.getPossibleValues()) {
if (needsComma) {
toReturn.append(",");
} else {
needsComma = true;
}
toReturn.append("'" + value + "':");
toReturn.append(counter++);
}
toReturn.append("};");
}
return toReturn.toString();
}
}