All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.resources.gss.CreateRuntimeConditionalNodes Maven / Gradle / Ivy

The newest version!
/*
 * 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.resources.gss;

import com.google.gwt.resources.gss.ast.CssJavaExpressionNode;
import com.google.gwt.resources.gss.ast.CssRuntimeConditionalRuleNode;
import com.google.gwt.thirdparty.common.css.compiler.ast.CssAtRuleNode.Type;
import com.google.gwt.thirdparty.common.css.compiler.ast.CssBooleanExpressionNode;
import com.google.gwt.thirdparty.common.css.compiler.ast.CssCompilerPass;
import com.google.gwt.thirdparty.common.css.compiler.ast.CssConditionalBlockNode;
import com.google.gwt.thirdparty.common.css.compiler.ast.CssConditionalRuleNode;
import com.google.gwt.thirdparty.common.css.compiler.ast.CssValueNode;
import com.google.gwt.thirdparty.common.css.compiler.ast.DefaultTreeVisitor;
import com.google.gwt.thirdparty.common.css.compiler.ast.MutatingVisitController;
import com.google.gwt.thirdparty.guava.common.collect.Lists;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Visitor that handles conditional nodes with conditions that need to be evaluated at runtime.
 *
 * 

The corresponding GSS handled by this pass looks like: * *

 *   @if(eval("com.foo.BAR")) {
 *   }
 *   @elseif(eval("com.foo.bar()")) {
 *   }
 * }
 * 
*/ public class CreateRuntimeConditionalNodes extends DefaultTreeVisitor implements CssCompilerPass { // TODO(jdr): valid input like eval('foo(")\')")') will break this regex private static final Pattern EVAL_FUNCTION = Pattern.compile("^eval\\(([\"'])(((?!\\1).)*)\\1\\)$"); private final MutatingVisitController visitController; public CreateRuntimeConditionalNodes(MutatingVisitController visitController) { this.visitController = visitController; } @Override public boolean enterConditionalBlock(CssConditionalBlockNode block) { // We have to visit all the CssConditionalRuleNode when we visit the CssConditionalBlockNode // parent node because we are going to replace CssConditionalRuleNode by another node and // unfortunately the visitController doesn't support to replace a CssConditionalRuleNode and // we have to do it manually. That implies that the new nodes won't be visited by the // visitor if we do that during the visit of the CssConditionalRuleNodes and they can contain // other CssConditionalBlockNodes that won't be visited. // Once MutatingVisitController supports replacement of CssConditionalRuleNode, // we will be able to visit CssConditionalRuleNode directly. // Make a copy in order to avoid ConcurrentModificationException List children = Lists.newArrayList(block.getChildren()); for (CssConditionalRuleNode ruleNode : children) { visitConditionalRule(ruleNode, block); } return true; } private void visitConditionalRule(CssConditionalRuleNode node, CssConditionalBlockNode parent) { if (node.getType() != Type.ELSE) { CssBooleanExpressionNode nodeCondition = node.getCondition(); String condition = extractRuntimeCondition(nodeCondition); if (condition != null) { CssJavaExpressionNode newNode = new CssJavaExpressionNode(condition, nodeCondition.getSourceCodeLocation()); CssRuntimeConditionalRuleNode newRuleNode = new CssRuntimeConditionalRuleNode(node, newNode); // Unfortunately visitController.replaceCurrentBlockChildWith doesn't work with // CssConditionnalRuleNode int index = parent.getChildren().indexOf(node); parent.replaceChildAt(index, Lists.newArrayList(newRuleNode)); } } } private String extractRuntimeCondition(CssValueNode node) { Matcher m = EVAL_FUNCTION.matcher(node.getValue()); return m.matches() ? m.group(2) : null; } @Override public void runPass() { visitController.startVisit(this); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy