Package com.google.template.soy.parsepasses

Source Code of com.google.template.soy.parsepasses.CheckCallsVisitor

/*
* Copyright 2012 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.template.soy.parsepasses;

import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.template.soy.soytree.AbstractSoyNodeVisitor;
import com.google.template.soy.soytree.CallBasicNode;
import com.google.template.soy.soytree.CallDelegateNode;
import com.google.template.soy.soytree.CallNode;
import com.google.template.soy.soytree.CallParamNode;
import com.google.template.soy.soytree.SoyFileSetNode;
import com.google.template.soy.soytree.SoyNode;
import com.google.template.soy.soytree.SoyNode.ParentSoyNode;
import com.google.template.soy.soytree.SoySyntaxExceptionUtils;
import com.google.template.soy.soytree.TemplateNode;
import com.google.template.soy.soytree.TemplateNode.SoyDocParam;
import com.google.template.soy.soytree.TemplateRegistry;
import com.google.template.soy.soytree.TemplateRegistry.DelegateTemplateDivision;

import java.util.List;
import java.util.Set;


/**
* Visitor for running some sanity checks on calls.
*
* <p>Important: Do not use outside of Soy code (treat as superpackage-private).
*
* @author Kai Huang
*/
public class CheckCallsVisitor extends AbstractSoyNodeVisitor<List<String>> {


  /** A template registry built from the Soy tree. */
  private TemplateRegistry templateRegistry;


  @Override public List<String> exec(SoyNode soyNode) {

    Preconditions.checkArgument(soyNode instanceof SoyFileSetNode);

    templateRegistry = new TemplateRegistry((SoyFileSetNode) soyNode);
    super.exec(soyNode);

    return null;
  }


  // -----------------------------------------------------------------------------------------------
  // Implementations for specific nodes.


  @Override protected void visitCallNode(CallNode node) {

    // Recurse.
    visitChildren(node);

    // If all the data keys being passed are listed using 'param' commands, then check that all
    // required params of the callee are included.
    if (! node.isPassingData()) {

      // Get the callee node (basic or delegate).
      TemplateNode callee;
      if (node instanceof CallBasicNode) {
        callee = templateRegistry.getBasicTemplate(((CallBasicNode) node).getCalleeName());
      } else {
        Set<DelegateTemplateDivision> divisions =
            templateRegistry.getDelTemplateDivisionsForAllVariants(
                ((CallDelegateNode) node).getDelCalleeName());
        if (divisions != null) {
          callee = Iterables.get(
              Iterables.getFirst(divisions, null).delPackageNameToDelTemplateMap.values(), 0);
        } else {
          callee = null;
        }
      }

      // Do the check if the callee node has SoyDoc.
      if (callee != null && callee.getSoyDocParams() != null) {
        // Get param keys passed by caller.
        Set<String> callerParamKeys = Sets.newHashSet();
        for (CallParamNode callerParam : node.getChildren()) {
          callerParamKeys.add(callerParam.getKey());
        }
        // Check param keys required by callee.
        List<String> missingParamKeys = Lists.newArrayListWithCapacity(2);
        for (SoyDocParam calleeParam : callee.getSoyDocParams()) {
          if (calleeParam.isRequired && ! callerParamKeys.contains(calleeParam.key)) {
            missingParamKeys.add(calleeParam.key);
          }
        }
        // Report errors.
        if (missingParamKeys.size() > 0) {
          String errorMsgEnd = (missingParamKeys.size() == 1) ?
              "param '" + missingParamKeys.get(0) + "'" : "params " + missingParamKeys;
          throw SoySyntaxExceptionUtils.createWithNode(
              String.format(
                  "Call to '%s' is missing required %s.",
                  callee.getTemplateNameForUserMsgs(), errorMsgEnd),
              node);
        }
      }
    }
  }


  // -----------------------------------------------------------------------------------------------
  // Fallback implementation.


  @Override protected void visitSoyNode(SoyNode node) {
    if (node instanceof ParentSoyNode<?>) {
      visitChildren((ParentSoyNode<?>) node);
    }
  }

}
TOP

Related Classes of com.google.template.soy.parsepasses.CheckCallsVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.