@@ -94,6 +94,11 @@ module Vue {
9494 )
9595 }
9696
97+ /**
98+ * Gets the template element used by this instance, if any.
99+ */
100+ abstract Template:: Element getTemplateElement ( ) ;
101+
97102 /**
98103 * Gets the node for the `data` option object of this instance.
99104 */
@@ -245,6 +250,8 @@ module Vue {
245250 }
246251
247252 override DataFlow:: Node getOwnOption ( string name ) { result = def .getOptionArgument ( 0 , name ) }
253+
254+ override Template:: Element getTemplateElement ( ) { none ( ) }
248255 }
249256
250257 /**
@@ -264,6 +271,8 @@ module Vue {
264271 }
265272
266273 override DataFlow:: Node getOwnOption ( string name ) { result = extend .getOptionArgument ( 0 , name ) }
274+
275+ override Template:: Element getTemplateElement ( ) { none ( ) }
267276 }
268277
269278 /**
@@ -291,6 +300,8 @@ module Vue {
291300 or
292301 result = MkExtendedVue ( extend ) .( ExtendedVue ) .getOption ( name )
293302 }
303+
304+ override Template:: Element getTemplateElement ( ) { none ( ) }
294305 }
295306
296307 /**
@@ -310,6 +321,8 @@ module Vue {
310321 }
311322
312323 override DataFlow:: Node getOwnOption ( string name ) { result = def .getOptionArgument ( 1 , name ) }
324+
325+ override Template:: Element getTemplateElement ( ) { none ( ) }
313326 }
314327
315328 /**
@@ -320,6 +333,14 @@ module Vue {
320333
321334 SingleFileComponent ( ) { this = MkSingleFileComponent ( file ) }
322335
336+ override Template:: Element getTemplateElement ( ) {
337+ exists ( HTML:: Element e | result .( Template:: HtmlElement ) .getElement ( ) = e |
338+ e .getFile ( ) = file and
339+ e .getName ( ) = "template" and
340+ e .isTopLevel ( )
341+ )
342+ }
343+
323344 override predicate hasLocationInfo (
324345 string filepath , int startline , int startcolumn , int endline , int endcolumn
325346 ) {
@@ -386,6 +407,62 @@ module Vue {
386407 override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
387408 pred = src and succ = this
388409 }
410+
411+ }
412+
413+ /*
414+ * Provides classes for working with Vue templates.
415+ */
416+ module Template {
417+ // Currently only supports HTML elements, but it may be possible to parse simple string templates later
418+ private newtype TElement =
419+ MkHtmlElement ( HTML:: Element e ) { exists ( VueFile f | e .getFile ( ) = f ) }
420+
421+ /**
422+ * An element of a template.
423+ */
424+ abstract class Element extends TElement {
425+ /** Gets a textual representation of this element. */
426+ string toString ( ) { result = "<" + getName ( ) + ">...</>" }
427+
428+ /**
429+ * Holds if this element is at the specified location.
430+ * The location spans column `startcolumn` of line `startline` to
431+ * column `endcolumn` of line `endline` in file `filepath`.
432+ * For more information, see
433+ * [LGTM locations](https://lgtm.com/help/ql/locations).
434+ */
435+ predicate hasLocationInfo (
436+ string filepath , int startline , int startcolumn , int endline , int endcolumn
437+ ) {
438+ filepath = "" and
439+ startline = 0 and
440+ startcolumn = 0 and
441+ endline = 0 and
442+ endcolumn = 0
443+ }
444+
445+ abstract string getName ( ) ;
446+ }
447+
448+ /**
449+ * An HTML element as a template element.
450+ */
451+ class HtmlElement extends Element , MkHtmlElement {
452+ HTML:: Element elem ;
453+
454+ HtmlElement ( ) { this = MkHtmlElement ( elem ) }
455+
456+ override predicate hasLocationInfo (
457+ string filepath , int startline , int startcolumn , int endline , int endcolumn
458+ ) {
459+ elem .getLocation ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn )
460+ }
461+
462+ override string getName ( ) { result = elem .getName ( ) }
463+
464+ HTML:: Element getElement ( ) { result = elem }
465+ }
389466 }
390467
391468}
0 commit comments