/* * Copyright 2008 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.shared.internal; import com.google.common.base.Preconditions; import com.google.template.soy.soytree.AbstractSoyNodeVisitor; import com.google.template.soy.soytree.CallBasicNode; import com.google.template.soy.soytree.SoyFileNode; import com.google.template.soy.soytree.SoyNode; import com.google.template.soy.soytree.SoyNode.ParentSoyNode; import com.google.template.soy.soytree.TemplateNode; import java.util.LinkedHashSet; import java.util.Set; /** * Visitor for finding the templates called in a file that are not defined in the file. * * <p>Important: Only deals with basic callees (not delegates). Calls to delegates are not * applicable here because we cannot tell at compile time which delegate will be called (if any). * * <p>Precondition: All template and callee names should be full names (i.e. you must execute {@code * SetFullCalleeNamesVisitor} before executing this visitor). * * <p>{@link #exec} should be called on a {@code SoyFileNode}. The returned set will be the full * names of all templates called by the templates in this file that that not in this file. In other * words, if T is the set of templates in this file and U is the set of templates not in this file, * then the returned set consists of the full names of all templates in U called by any template in * T. * */ public final class FindCalleesNotInFileVisitor extends AbstractSoyNodeVisitor<Set<CallBasicNode>> { /** The names of templates defined in this file. */ private Set<String> templatesInFile; /** The call nodes of templates not defined in this file (the result). */ private Set<CallBasicNode> calleesNotInFile; @Override public Set<CallBasicNode> exec(SoyNode node) { Preconditions.checkArgument(node instanceof SoyFileNode); visit(node); return calleesNotInFile; } // ----------------------------------------------------------------------------------------------- // Implementations for specific nodes. @Override protected void visitSoyFileNode(SoyFileNode node) { templatesInFile = new LinkedHashSet<>(); for (TemplateNode template : node.getChildren()) { templatesInFile.add(template.getTemplateName()); } calleesNotInFile = new LinkedHashSet<>(); visitChildren(node); } @Override protected void visitCallBasicNode(CallBasicNode node) { String calleeName = node.getCalleeName(); if (!templatesInFile.contains(calleeName)) { calleesNotInFile.add(node); } visitChildren(node); } // ----------------------------------------------------------------------------------------------- // Fallback implementation. @Override protected void visitSoyNode(SoyNode node) { if (node instanceof ParentSoyNode<?>) { visitChildren((ParentSoyNode<?>) node); } } }