/* * Copyright (C) 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.clearsilver.jsilver.syntax; import com.google.clearsilver.jsilver.exceptions.JSilverBadSyntaxException; import com.google.clearsilver.jsilver.syntax.analysis.AnalysisAdapter; import com.google.clearsilver.jsilver.syntax.analysis.DepthFirstAdapter; import com.google.clearsilver.jsilver.syntax.node.ADataCommand; import com.google.clearsilver.jsilver.syntax.node.AInlineCommand; import com.google.clearsilver.jsilver.syntax.node.ANoopCommand; import com.google.clearsilver.jsilver.syntax.node.PCommand; import com.google.clearsilver.jsilver.syntax.node.TData; /** * Rewrites the AST to replace all 'inline' commands with their associated inner * command sub-tree, where all whitespace data commands have been removed. * *
The following template: *
* * * > " + x.foo + " <<"?> * * ** *
will render as if it had been written: *
* > " + x.foo + " <<"?> ** *
The inline command is intended only to allow neater template authoring. * As such there is a restriction that any data commands (ie, bare literal text) * inside an inline command can consist only of whitespace characters. This * limits the risk of accidentally modifying the template's output in an * unexpected way when using the inline command. Literal text may still be * rendered in an inlined section if it is part of a var command. * *
Data commands containing only whitespace are effectively removed by * replacing them with noop commands. These can be removed (if needed) by a * later optimization step but shouldn't cause any issues. */ public class InlineRewriter extends DepthFirstAdapter { /** * Inner visitor class to recursively replace data commands with noops. */ private static AnalysisAdapter WHITESPACE_STRIPPER = new DepthFirstAdapter() { @Override public void caseADataCommand(ADataCommand node) { TData data = node.getData(); if (isAllWhitespace(data.getText())) { node.replaceBy(new ANoopCommand()); return; } // TODO: Add more information here (line numbers etc...) throw new JSilverBadSyntaxException( "literal text in an inline block may only contain whitespace", data.getText(), null, data .getLine(), data.getPos(), null); } @Override public void caseAInlineCommand(AInlineCommand node) { // Once in an inline block, just remove any more we encounter. PCommand command = node.getCommand(); node.replaceBy(command); command.apply(this); } }; private static boolean isAllWhitespace(String s) { for (int i = 0; i < s.length(); i++) { if (!Character.isWhitespace(s.charAt(i))) { return false; } } return true; } /** * Removes data commands within an inline command. * * @throws JSilverBadSyntaxException if any data commands within the inline block contain * non-whitespace text. */ @Override public void caseAInlineCommand(AInlineCommand node) { node.getCommand().apply(WHITESPACE_STRIPPER); node.replaceBy(node.getCommand()); } }