|
1 | 1 | package com.semmle.js.extractor; |
2 | 2 |
|
| 3 | +import java.nio.file.Path; |
3 | 4 | import java.util.ArrayList; |
4 | 5 | import java.util.Collections; |
5 | 6 | import java.util.List; |
@@ -166,8 +167,10 @@ public class ASTExtractor { |
166 | 167 | private final Label toplevelLabel; |
167 | 168 | private final LexicalExtractor lexicalExtractor; |
168 | 169 | private final RegExpExtractor regexpExtractor; |
| 170 | + private final ExtractorConfig config; |
169 | 171 |
|
170 | | - public ASTExtractor(LexicalExtractor lexicalExtractor, ScopeManager scopeManager) { |
| 172 | + public ASTExtractor(ExtractorConfig config, LexicalExtractor lexicalExtractor, ScopeManager scopeManager) { |
| 173 | + this.config = config; |
171 | 174 | this.trapwriter = lexicalExtractor.getTrapwriter(); |
172 | 175 | this.locationManager = lexicalExtractor.getLocationManager(); |
173 | 176 | this.contextManager = new SyntacticContextManager(); |
@@ -1136,9 +1139,70 @@ public Label visit(Property nd, Context c) { |
1136 | 1139 | visit(nd.getDefaultValue(), propkey, 2, IdContext.varBind); |
1137 | 1140 | if (nd.isComputed()) trapwriter.addTuple("is_computed", propkey); |
1138 | 1141 | if (nd.isMethod()) trapwriter.addTuple("is_method", propkey); |
| 1142 | + |
| 1143 | + // Extract the value of a property named `template` as HTML, in order to support |
| 1144 | + // Angular2 components with an inline template. |
| 1145 | + if (!nd.isComputed() && "template".equals(tryGetIdentifierName(nd.getKey()))) { |
| 1146 | + extractStringValueAsHtml(nd.getValue()); |
| 1147 | + } |
| 1148 | + |
1139 | 1149 | return propkey; |
1140 | 1150 | } |
1141 | 1151 |
|
| 1152 | + /** |
| 1153 | + * Extracts the string value of <code>expr</code> as an HTML snippet. |
| 1154 | + */ |
| 1155 | + private void extractStringValueAsHtml(Expression expr) { |
| 1156 | + TextualExtractor textualExtractor = lexicalExtractor.getTextualExtractor(); |
| 1157 | + if (textualExtractor.isSnippet()) { |
| 1158 | + return; // do not create nested snippets |
| 1159 | + } |
| 1160 | + String source = tryGetStringValueFromExpression(expr); |
| 1161 | + if (source == null) { |
| 1162 | + return; |
| 1163 | + } |
| 1164 | + SourceLocation loc = expr.getLoc(); |
| 1165 | + Path originalFile = textualExtractor.getExtractedFile().toPath(); |
| 1166 | + Path vfile = originalFile.resolveSibling(originalFile.getFileName().toString() + "." + loc.getStart().getLine() + "." + loc.getStart().getColumn() + ".html"); |
| 1167 | + LocationManager innerLocationManager = new LocationManager( |
| 1168 | + locationManager.getSourceFile(), |
| 1169 | + locationManager.getTrapWriter(), |
| 1170 | + locationManager.getFileLabel()); |
| 1171 | + innerLocationManager.setStart(loc.getStart().getLine(), loc.getStart().getColumn()); |
| 1172 | + TextualExtractor innerTextualExtractor = new TextualExtractor( |
| 1173 | + trapwriter, |
| 1174 | + innerLocationManager, |
| 1175 | + source, |
| 1176 | + false, |
| 1177 | + getMetrics(), |
| 1178 | + vfile.toFile()); |
| 1179 | + HTMLExtractor html = HTMLExtractor.forEmbeddedHtml(config); |
| 1180 | + html.extract(innerTextualExtractor); |
| 1181 | + } |
| 1182 | + |
| 1183 | + private String tryGetIdentifierName(Expression e) { |
| 1184 | + return e instanceof Identifier ? ((Identifier)e).getName() : null; |
| 1185 | + } |
| 1186 | + |
| 1187 | + private String tryGetStringValueFromExpression(Expression e) { |
| 1188 | + if (e instanceof Literal) { |
| 1189 | + Literal lit = (Literal) e; |
| 1190 | + return lit.isStringLiteral() ? (String) lit.getValue() : null; |
| 1191 | + } |
| 1192 | + if (e instanceof TemplateLiteral) { |
| 1193 | + TemplateLiteral lit = (TemplateLiteral) e; |
| 1194 | + if (!lit.getExpressions().isEmpty()) { |
| 1195 | + return null; |
| 1196 | + } |
| 1197 | + StringBuilder sb = new StringBuilder(); |
| 1198 | + for (TemplateElement elm : lit.getQuasis()) { |
| 1199 | + sb.append(elm.getCooked()); |
| 1200 | + } |
| 1201 | + return sb.toString(); |
| 1202 | + } |
| 1203 | + return null; |
| 1204 | + } |
| 1205 | + |
1142 | 1206 | @Override |
1143 | 1207 | public Label visit(IfStatement nd, Context c) { |
1144 | 1208 | Label key = super.visit(nd, c); |
|
0 commit comments