Local scope clarification re:<cfsavecontent>

So I recently discovered CFLint…:wink:
I’ve been going through this legacy code, trying to fix potential scope problems, and I ran into this bit:

<cfset preString="">
<cfif isDefined("URL.Mode") and len(trim(URL.Mode)) gt 0>
  <cfset preString="#URL.Mode# ">
</cfif>
<CFSAVECONTENT variable="myBreadcrumbs">
  <A HREF="#thisPageStruct['Level1URL']#">#thisPageStruct["Level1Text"]#</A> ->
  <A HREF="#thisPageStruct['Level2URL']#">#thisPageStruct["Level2Text"]#</A> ->
  <A HREF="#thisPageStruct['Level3URL']##qString#" target="iRight">#preString##thisPageStruct["Level3Text"]#</A>
</CFSAVECONTENT>

cflint warns: “Variable preString is not declared with a var statement.cflint(MISSING_VAR)”

so I changed the first line to

<cfset var preString="">

but now cflint says: “Local variable preString is not used in function getBreadcrumbs. Consider removing it.cflint(UNUSED_LOCAL_VARIABLE)”

So now I’m wondering if this is a problem with cflint’s parser or with my understanding of the code. The variable preString is used within the <cfsavecontent> tag…so I was wondering if <cfsavecontent> maybe creates a new local scope?

Then I realized that the tag’s contents also reference local variables qString and thisPageStruct, which are declared earlier in the code using var. Turns out I’m getting the same UNUSED_LOCAL_VARIABLE error at

<cfset var qString = "">

Confusingly, the declaration for thisPageStruct shows a different cflint error: “Variable has prefix or postfix thisPageStruct and could be named better.cflint(VAR_HAS_PREFIX_OR_POSTFIX)”.

CFLint could probably use better documentation for its rules but anyways… through trial and error, it appears that it disapproves of variable names like thisVal (or myThing or qStuff). OK, whatever… I renamed it to page and it’s fine…

So anyways, after cleaning up the remaining CFLint variable name complaints (or, to be honest, just disabling them…I’ll go crazy “fixing” every variable name in the website), I’ve got something like this:

<cfset var qString = "">
<cfif isDefined("CGI.QUERY_STRING") AND len(CGI.QUERY_STRING) NEQ "0">
  <cfset qString="?#CGI.QUERY_STRING#">
</cfif>
<cfset var page = ...>

...
<cfif ...>
  ...
<cfelseif page["Level4Text"] is NULL>
  <cfset preString="">
  <cfif isDefined("URL.Mode") and len(trim(URL.Mode)) gt 0>
    <cfset preString="#URL.Mode# ">
  </cfif>
  <CFSAVECONTENT variable="myBreadcrumbs">
    <A HREF="#page['Level1URL']#">#page["Level1Text"]#</A> ->
    <A HREF="#page['Level2URL']#">#page["Level2Text"]#</A> ->
    <A HREF="#page['Level3URL']##qString#" target="iRight">#preString##page["Level3Text"]#</A>   
  </CFSAVECONTENT>
<cfelse>
  ...

I’m still getting UNUSED_LOCAL_VARIABLE for qString and preString but no such warnings for page. Since page is referenced outside of the <cfsavecontent> tag, I’m still unsure whether this is a problem with cflint’s parser or if it is legitimately warning me about a new local scope within the tag content.

Edit: hmm, actually…if it was a new local scope, shouldn’t it warn me about accessing undeclared variables within the tag content?

After some more experimentation, my theory is that CFLint’s parser cannot see "#variable#" references inside strings at all. At first I thought it might just be a problem with "#var1##var2#", or the fact that it’s not wrapped with <cfoutput>, but neither of those changes made any difference.

Similarly, if I remove the variable declaration and assignment entirely, cflint still doesn’t see any problem with the string containing #preString# :confused:

That’s too bad…really undermines the utility of a linter if it can’t see those variable references. I’d say most of the string manipulation in this app is done using that syntax…

pretty sure it’s a cflint problem.

check the issues Issues · cflint/CFLint · GitHub and file bug if t hasn’t been reported yet