@@ -214,7 +214,7 @@ module Templating {
214214 exists ( TemplateInstantiaton inst , API:: Node base , string name |
215215 base .getARhs ( ) = inst .getTemplateParamsNode ( ) and
216216 result = base .getMember ( name ) and
217- succ = inst .getTemplateFile ( ) .getAPlaceholder ( ) .getInnerTopLevel ( ) .getAVariableUse ( name )
217+ succ = inst .getTemplateFile ( ) .getAnImportedFile * ( ) . getAPlaceholder ( ) .getInnerTopLevel ( ) .getAVariableUse ( name )
218218 )
219219 or
220220 exists ( string prop , DataFlow:: SourceNode prev |
@@ -260,6 +260,11 @@ module Templating {
260260 abstract class TemplateFile extends File {
261261 /** Gets a placeholder tag in this file. */
262262 final TemplatePlaceholderTag getAPlaceholder ( ) { result .getFile ( ) = this }
263+
264+ /** Gets a template file referenced by this one via a template inclusion tag, such as `{% include foo %}` */
265+ TemplateFile getAnImportedFile ( ) {
266+ result = getAPlaceholder ( ) .( TemplateInclusionTag ) .getImportedFile ( )
267+ }
263268 }
264269
265270 /** Any HTML file, seen as a possible target for template instantiation. */
@@ -601,4 +606,47 @@ module Templating {
601606
602607 override DataFlow:: Node getARhs ( ) { none ( ) }
603608 }
609+
610+ /**
611+ * A template tag which causes another template file to be instantiated using the same variables as the current one.
612+ *
613+ * Examples:
614+ * - `{% include foo/bar %}`
615+ * - `{% include "../foo/bar.html" %}`
616+ * - `<% include foo/bar %>`
617+ * - `{{!< foo/bar }}`
618+ * - `{{> foo/bar }}`
619+ */
620+ class TemplateInclusionTag extends TemplatePlaceholderTag {
621+ string rawPath ;
622+
623+ TemplateInclusionTag ( ) {
624+ rawPath = getRawText ( ) .regexpCapture ( "[{<]% *(?:import|include|extend|require)s? *(?:[(] *)?['\"]?(.*?)['\"]? *(?:[)] *)?%[}>]" , 1 )
625+ or
626+ rawPath = getRawText ( ) .regexpCapture ( "\\{\\{!?[<>](.*?)\\}\\}" , 1 )
627+ }
628+
629+ /** Gets the imported path (normalized). */
630+ string getPath ( ) {
631+ result = rawPath .trim ( ) .replaceAll ( "\\" , "/" ) .regexpReplaceAll ( "^\\./" , "" )
632+ }
633+
634+ /** Gets the file referenced by this inclusion tag. */
635+ TemplateFile getImportedFile ( ) {
636+ result = getPath ( ) .( TemplateFileReferenceString ) .getTemplateFile ( )
637+ }
638+ }
639+
640+ /** The imported string from a template inclusion tag. */
641+ private class TemplateInclusionPathString extends TemplateFileReferenceString {
642+ TemplateInclusionTag tag ;
643+
644+ TemplateInclusionPathString ( ) {
645+ this = tag .getPath ( )
646+ }
647+
648+ override Folder getContextFolder ( ) {
649+ result = tag .getFile ( ) .getParentContainer ( )
650+ }
651+ }
604652}
0 commit comments