Package: MergeVisitor

MergeVisitor

nameinstructionbranchcomplexitylinemethod
MergeVisitor(TemplateManager, TemplateCallable[])
M: 0 C: 26
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
addDefaults(TemplateCallable[])
M: 2 C: 37
95%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 1 C: 4
80%
M: 0 C: 1
100%
defaultINode(INode, StringWriter)
M: 55 C: 33
38%
M: 4 C: 4
50%
M: 4 C: 1
20%
M: 9 C: 10
53%
M: 0 C: 1
100%
getMergeErrors()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getTemplateManager()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getUnsupportedInTargLang()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
hasMergeErrors()
M: 2 C: 6
75%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 1
100%
M: 0 C: 1
100%
hasUnsupportedTargLangNodes()
M: 2 C: 9
82%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 0 C: 2
100%
M: 0 C: 1
100%
init()
M: 0 C: 11
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
initCodeGenContext(INode, TemplateCallable[])
M: 0 C: 36
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
register(MergerObserver)
M: 9 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
setTemplateManager(TemplateManager)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
unregister(MergerObserver)
M: 10 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * #%~
3: * VDM Code Generator
4: * %%
5: * Copyright (C) 2008 - 2014 Overture
6: * %%
7: * This program is free software: you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as
9: * published by the Free Software Foundation, either version 3 of the
10: * License, or (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public
18: * License along with this program. If not, see
19: * <http://www.gnu.org/licenses/gpl-3.0.html>.
20: * #~%
21: */
22: package org.overture.codegen.merging;
23:
24: import java.io.StringWriter;
25: import java.util.HashSet;
26: import java.util.LinkedList;
27: import java.util.List;
28: import java.util.Set;
29: import java.util.Stack;
30:
31: import org.apache.velocity.Template;
32: import org.apache.velocity.runtime.parser.ParseException;
33: import org.overture.codegen.ir.INode;
34: import org.overture.codegen.ir.IrNodeInfo;
35: import org.overture.codegen.ir.analysis.AnalysisException;
36: import org.overture.codegen.ir.analysis.QuestionAdaptor;
37: import org.overture.codegen.utils.GeneralUtils;
38:
39: public class MergeVisitor extends QuestionAdaptor<StringWriter>
40:                 implements MergeCoordinator
41: {
42:         private static final String NODE_KEY = "node";
43:
44:         private TemplateManager templates;
45:         private TemplateCallable[] templateCallables;
46:         private Set<IrNodeInfo> unsupportedInTargLang;
47:
48:         // Since generating code is done by merging templates recursively a stack is used to manage the node contexts used
49:         // by the template engine.
50:         // This is needed to avoid overwriting variables already introduced by other templates e.g. #set( $type = ... ).
51:         private Stack<MergeContext> nodeContexts;
52:
53:         private List<Exception> mergeErrors;
54:
55:         private MergerObserver mergeObserver;
56:
57:         /**
58:          * Extensible constructor.
59:          *
60:          * @param templateManager
61:          * @param templateCallables
62:          */
63:         public MergeVisitor(TemplateManager templateManager,
64:                         TemplateCallable[] templateCallables)
65:         {
66:                 this.templates = templateManager;
67:                 this.nodeContexts = new Stack<MergeContext>();
68:                 this.templateCallables = addDefaults(templateCallables);
69:                 this.mergeErrors = new LinkedList<Exception>();
70:                 this.unsupportedInTargLang = new HashSet<IrNodeInfo>();
71:         }
72:
73:         /**
74:          * Enables the static methods of the java.lang.String class to be called from the templates. If the key "String" is
75:          * already reserved by the user, this method simply returns the input parameter.
76:          *
77:          * @param userCallables
78:          * @return all the template callables
79:          */
80:         public TemplateCallable[] addDefaults(TemplateCallable[] userCallables)
81:         {
82:                 TemplateCallable strFunctionality = new TemplateCallable(String.class.getSimpleName(), String.class);
83:
84:•                for (TemplateCallable u : userCallables)
85:                 {
86:•                        if (u.equals(strFunctionality))
87:                         {
88:                                 return userCallables;
89:                         }
90:                 }
91:
92:                 return GeneralUtils.concat(userCallables, new TemplateCallable[] {
93:                                 strFunctionality });
94:         }
95:
96:         public List<Exception> getMergeErrors()
97:         {
98:                 return mergeErrors;
99:         }
100:
101:         public boolean hasMergeErrors()
102:         {
103:•                return !mergeErrors.isEmpty();
104:         }
105:
106:         public Set<IrNodeInfo> getUnsupportedInTargLang()
107:         {
108:                 return unsupportedInTargLang;
109:         }
110:
111:         public boolean hasUnsupportedTargLangNodes()
112:         {
113:•                return unsupportedInTargLang != null
114:•                                && !unsupportedInTargLang.isEmpty();
115:         }
116:
117:         public void init()
118:         {
119:                 // Avoid clearing the data structures if others are using them
120:                 mergeErrors = new LinkedList<Exception>();
121:                 unsupportedInTargLang = new HashSet<IrNodeInfo>();
122:         }
123:
124:         private void initCodeGenContext(INode node,
125:                         TemplateCallable[] templateCallables)
126:         {
127:                 MergeContext nodeContext = new MergeContext();
128:                 nodeContext.put(NODE_KEY, node);
129:
130:•                for (TemplateCallable callable : templateCallables)
131:                 {
132:                         nodeContext.put(callable.getKey(), callable.getCallable());
133:                 }
134:
135:                 nodeContexts.push(nodeContext);
136:         }
137:
138:         @Override
139:         public void defaultINode(INode node, StringWriter question)
140:                         throws AnalysisException
141:         {
142:                 initCodeGenContext(node, templateCallables);
143:
144:                 try
145:                 {
146:                         Template template = templates.getTemplate(node.getClass());
147:
148:•                        if (template == null)
149:                         {
150:                                 unsupportedInTargLang.add(new IrNodeInfo(node, "Template could not be found."));
151:                         }
152:                         try
153:                         {
154:•                                if (mergeObserver != null)
155:                                 {
156:                                         mergeObserver.preMerging(node, question);
157:                                 }
158:
159:•                                if (template != null)
160:                                 {
161:                                         template.merge(nodeContexts.pop().getVelocityContext(), question);
162:                                 } else
163:                                 {
164:                                         question.write(String.format("/* Undefined template: %s */", node.getClass().getSimpleName()));
165:                                 }
166:
167:•                                if (mergeObserver != null)
168:                                 {
169:                                         mergeObserver.nodeMerged(node, question);
170:                                 }
171:                         } catch (Exception e)
172:                         {
173:                                 mergeErrors.add(e);
174:                         }
175:                 } catch (ParseException e)
176:                 {
177:                         unsupportedInTargLang.add(new IrNodeInfo(node, "Parse error in template.\n"
178:                                         + e.getMessage()));
179:                 }
180:         }
181:
182:         @Override
183:         public void register(MergerObserver obs)
184:         {
185:•                if (obs != null && mergeObserver == null)
186:                 {
187:                         mergeObserver = obs;
188:                 }
189:         }
190:
191:         @Override
192:         public void unregister(MergerObserver obs)
193:         {
194:•                if (obs != null && mergeObserver == obs)
195:                 {
196:                         mergeObserver = null;
197:                 }
198:         }
199:
200:         public TemplateManager getTemplateManager()
201:         {
202:                 return templates;
203:         }
204:
205:         public void setTemplateManager(TemplateManager templates)
206:         {
207:                 this.templates = templates;
208:         }
209: }