1 | // Copyright (C) 2008 Google Inc. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | package com.google.caja.parser.js; |
16 | |
17 | import com.google.caja.lexer.FilePosition; |
18 | import com.google.caja.lexer.TokenConsumer; |
19 | import com.google.caja.parser.AbstractParseTreeNode; |
20 | import com.google.caja.parser.ParseTreeNode; |
21 | import com.google.caja.render.Concatenator; |
22 | import com.google.caja.render.JsPrettyPrinter; |
23 | import com.google.caja.reporting.RenderContext; |
24 | import com.google.caja.util.Callback; |
25 | |
26 | import java.io.IOException; |
27 | import java.util.List; |
28 | |
29 | /** |
30 | * Translates to a cajoled module which renders as: <tt>___.loadModule...</tt>. |
31 | * This is not a core JavaScript parse tree node — it is never produced by |
32 | * {@link Parser}. |
33 | * |
34 | * @author erights@gmail.com |
35 | * @author ihab.awad@gmail.com |
36 | */ |
37 | public final class UncajoledModule extends AbstractParseTreeNode { |
38 | /** @param value unused. This ctor is provided for reflection. */ |
39 | @ReflectiveCtor |
40 | public UncajoledModule(FilePosition pos, |
41 | Void value, |
42 | List<? extends Block> children) { |
43 | this(pos, children.get(0)); |
44 | assert children.size() == 1; |
45 | } |
46 | |
47 | public UncajoledModule(FilePosition pos, Block body) { |
48 | super(pos, Block.class); |
49 | createMutation().appendChild(body).execute(); |
50 | } |
51 | |
52 | public UncajoledModule(Block body) { |
53 | this(FilePosition.UNKNOWN, body); |
54 | } |
55 | |
56 | @Override |
57 | protected void childrenChanged() { |
58 | super.childrenChanged(); |
59 | if (children().size() != 1) { |
60 | throw new IllegalStateException( |
61 | "An UncajoledModule may only have one child"); |
62 | } |
63 | ParseTreeNode module = children().get(0); |
64 | if (!(module instanceof Block)) { |
65 | throw new ClassCastException("Expected block, not " + module); |
66 | } |
67 | } |
68 | |
69 | @Override |
70 | public Object getValue() { return null; } |
71 | |
72 | @Override |
73 | public List<? extends Block> children() { |
74 | return childrenAs(Block.class); |
75 | } |
76 | |
77 | public Block getModuleBody() { return children().get(0); } |
78 | |
79 | public final TokenConsumer makeRenderer( |
80 | Appendable out, Callback<IOException> exHandler) { |
81 | return new JsPrettyPrinter(new Concatenator(out, exHandler)); |
82 | } |
83 | |
84 | public void render(RenderContext rc) { |
85 | TokenConsumer out = rc.getOut(); |
86 | out.consume("/* Start Uncajoled Module */"); |
87 | out.consume("throw"); |
88 | out.consume("'Uncajoled Module must never be executed'"); |
89 | out.consume(";"); |
90 | getModuleBody().render(rc); |
91 | out.consume("/* End Uncajoled Module */"); |
92 | } |
93 | } |