Skip to content

Commit da1ffcf

Browse files
author
Esben Sparre Andreasen
committed
JS: introduce Vue Template Element
1 parent 9f4f945 commit da1ffcf

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

javascript/ql/src/semmle/javascript/frameworks/Vue.qll

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
| single-component-file-1.vue:1:1:3:11 | <template>...</> |
2+
| single-component-file-1.vue:2:5:10:8 | <p>...</> |
3+
| single-component-file-1.vue:4:1:8:9 | <script>...</> |
4+
| single-component-file-1.vue:9:1:10:8 | <style>...</> |
5+
| single-file-component-2.vue:1:1:3:11 | <template>...</> |
6+
| single-file-component-2.vue:2:5:11:8 | <p>...</> |
7+
| single-file-component-2.vue:4:1:9:9 | <script>...</> |
8+
| single-file-component-2.vue:10:1:11:8 | <style>...</> |
9+
| single-file-component-3.vue:1:1:3:11 | <template>...</> |
10+
| single-file-component-3.vue:2:5:7:8 | <p>...</> |
11+
| single-file-component-3.vue:4:1:5:9 | <script>...</> |
12+
| single-file-component-3.vue:6:1:7:8 | <style>...</> |
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import javascript
2+
3+
select any(Vue::Template::Element e)

0 commit comments

Comments
 (0)