Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rule UNUSED_LOCAL_VARIABLE has issues with several tags #339

Closed
HarryMuc opened this issue Jul 6, 2017 · 28 comments
Closed

Rule UNUSED_LOCAL_VARIABLE has issues with several tags #339

HarryMuc opened this issue Jul 6, 2017 · 28 comments
Assignees
Labels
Milestone

Comments

@HarryMuc
Copy link

HarryMuc commented Jul 6, 2017

CFLint return the error message: local variable X is not used in function Y

But the local variables are used in tags like cfloop, cflocation, cfcookie, ...:

<cfset var lLoginURLParams = stContens.security.lLoginURLParams>
    <cfloop list="#lLoginURLParams#" index="sParam">

<cfset var sCoreURL = stContens.sCoreURL>
    <cflocation url="#sCoreURL#contens/index.cfm#sLoginParams#" addtoken="No">

<cfset var sRememberUserCookieKey = getRememberUserLoginCookieName()>
    <cfcookie name="#sRememberUserCookieKey#" value="#sCookieValue#" expires="#sExpirePeriod#">
ryaneberly added a commit that referenced this issue Jul 17, 2017
@ryaneberly ryaneberly self-assigned this Jul 17, 2017
@ryaneberly ryaneberly added this to the 1.2.0 milestone Jul 17, 2017
@ryaneberly
Copy link
Contributor

These are implemented. Thanks for reporting it.

@HarryMuc
Copy link
Author

Thanks a lot Ryan! Will test asap

@HarryMuc
Copy link
Author

HarryMuc commented Jul 17, 2017

Sorry, this issue is not fixed with 1.2.0 - I still have lots of false positives
e.g.

<cfset var qWork = "">
...
<cfquery name="qWork" datasource="#variables.sPublishDataSource#">
...
</cfquery>

ryaneberly added a commit that referenced this issue Jul 18, 2017
fixed.
@ryaneberly
Copy link
Contributor

I'm assuming you meant:

<cfset var sPublishDataSource= "">
...
<cfquery name="qWork" datasource="#variables.sPublishDataSource#">
...
</cfquery>

I added @Datasource to the expressions that are considered, and fixed an issue with the variables scope.

@ryaneberly ryaneberly reopened this Jul 18, 2017
@HarryMuc
Copy link
Author

HarryMuc commented Jul 18, 2017

No, I didn't mean the datasource attribute - the name attribute is important.
We always local scope the query name, also the loop index ...

atm the rule returns false positives for:

  1. LOOP
<cfset var iIdx = "">
<cfloop list="#arguments.lID#" index="iIdx">...</cfloop>
<cfset var ifolder = 0>
<cfloop collection="#attributes.foldermapping#" item="ifolder">...</cfloop>
  1. QUERY
<cfset var qAllPages = "">
<cfquery name="qAllPages" datasource="#variables.sPublishDataSource#">...</cfquery>
  1. LOCAL
<cfset var local = {}>
<cfset local.stEditor = ...>

@ryaneberly
Copy link
Contributor

ryaneberly commented Jul 18, 2017

@derrick13 ,
Thanks, are you saying that when the query name is declared, we should consider that variable used?

I would expect this to flag unused:

<cfset var qAllPages = "">
<cfquery name="qAllPages" datasource="#variables.sPublishDataSource#">...</cfquery>

and this to NOT flag it:

<cfset var qAllPages = "">
<cfquery name="qAllPages" datasource="#variables.sPublishDataSource#">...</cfquery>
<cfloop query="qAllPages">...</cfloop>

Am I missing something?

@HarryMuc
Copy link
Author

HarryMuc commented Jul 18, 2017 via email

@ryaneberly
Copy link
Contributor

ryaneberly commented Jul 18, 2017 via email

@HarryMuc
Copy link
Author

HarryMuc commented Jul 18, 2017 via email

@TheRealAgentK
Copy link
Collaborator

@ryaneberly @derrick13

As opposed to Ryan, I personally would treat both cases below as NOT flagging UNUSED_LOCAL_VARIABLE. To me it doesn't matter if you use qAllPages in a loop or output or whatever after the query - the mere fact that it's used as a name for the query should be enough to not kick off this rule.

<cfset var qAllPages = "">
<cfquery name="qAllPages" datasource="#variables.sPublishDataSource#">...</cfquery>
<cfset var qAllPages = "">
<cfquery name="qAllPages" datasource="#variables.sPublishDataSource#">...</cfquery>
<cfloop query="qAllPages">...</cfloop>

@ryaneberly
Copy link
Contributor

@TheRealAgentK, I'm good with that. Don't want to ding someone for using a best practice that makes up for a coldfusion deficiency.

ryaneberly added a commit that referenced this issue Jul 18, 2017
@ryaneberly
Copy link
Contributor

@derrick13 ,
I took care of cfquery/@name, cfloop/@Index, and cfloop/@item.. Help with an exhaustive list would be great.

Still looking at the local struct issue.

@TheRealAgentK
Copy link
Collaborator

TheRealAgentK commented Jul 18, 2017

Here's some - but it'd be good if @derrick13 could verify those first.

cfchart / name
cfdocument / name
cfftp / name when action = "listDir"
cfhtmltopdf / name
cfhttp / resultname
cfimage / name
cfimap / name when action GetAll, GetHeaderOnly or ListAllFolders
cfldap / name when action Query
cfoutput / query
cfpdf / name
cfreport / name
cfsavecontent / name
cfstoreproc / result
cfxml / variable

also: this is just what I could easily think of - most likely not exhaustive.

ryaneberly added a commit that referenced this issue Jul 19, 2017
ryaneberly added a commit that referenced this issue Jul 19, 2017
fix local false positive
@ryaneberly
Copy link
Contributor

@derrick13
The example that uses

<cfset var local = {}>
<cfset local.stEditor = ...>

is an interesting one. It was a false positive because local is a scope. The false positive is removed. However, it seems to me that initializing local is bad practice now that local is a scope. Thoughts?

@ryaneberly
Copy link
Contributor

@TheRealAgentK

Your list is implemented. It is parameterized in cflint.definition.json.

ryaneberly added a commit that referenced this issue Jul 19, 2017
fix test
@HarryMuc
Copy link
Author

Wow, thanks for your work Ryan - and for the list Kai!
The rule now works better and better!
I waded through a lot of files and it is almost perfect now.
Only these 3 false positives where still found:

  1. var scoped method used in query
	<cfset var oQueryFct = super.getAppHelper().instanceFactory("contenscms.util.system.queryfct")>

	<cfquery datasource="#variables.stContens.sDatasource#">
	SELECT ...
	WHERE #oQueryFct.cutIDlist("accessdata_ID", arguments.idList)#
	</cfquery>
  1. var scoped variable used in query
	<cfset var iThisServerId = oServersDatamanager.findIdByServername(servername=variables.stContens.sServerName)>

	<cfquery name="qConnections" datasource="#variables.stContens.sDataSource#" maxrows="1">
	SELECT	...
	WHERE	co_servers_connections_rel.server_ID = #iThisServerId#
	</cfquery>
  1. var scoped cfheader file attribute
	<cfset var sFile = "#variables.sCmfAppDir#cmf-#arguments.sModuleFolder#.zip">

	<cfheader name="content-disposition" value="inline; filename=cmf-#arguments.sModuleFolder#.zip"
	><cfcontent type="application/x-zip-compressed" file="#sFile#" deletefile="No" reset="yes"
	><cfabort>

@HarryMuc
Copy link
Author

Found another one:
4) var scoped variable in cflog text

<cfset var sSecureFolder = expandPath("/#variables.stContens.applicationname#/_secure/collections/")>

<cflog file="content_errors" text="Please check the lucene collections in the folder #sSecureFolder# and manually remove the file 'write.lock'! #cfcatch.message#">

@HarryMuc
Copy link
Author

@ryaneberly "... it seems to me that initializing local is bad practice now that local is a scope ..."

Definitely, it is bad practice now but some of our code is old and was written before ACF 9 (which introduced the local scope)

See also:
http://forta.com/blog/index.cfm/2009/6/21/The-New-ColdFusion-LOCAL-Scope
http://blog.adamcameron.me/2013/12/34-dumb-things-coldfusion-does.html
http://www.carehart.org/blog/client/index.cfm/2010/3/4/resources_on_the_var_scope_problem

@ryaneberly
Copy link
Contributor

@derrick13 would it be valuable to add a different linting rule for the declaration of a "local" variable?

@HarryMuc
Copy link
Author

imho it would just complicate the configuration, I wouldn't add a new rule

ryaneberly added a commit that referenced this issue Jul 20, 2017
@ryaneberly
Copy link
Contributor

@derrick13, thanks for the detailed research. Much appreciated.

1 &2 - parsing cfquery is dicey -- suggest 1.3.0
3 - cfparser needs to support cfcontent cfparser/cfparser#81
4 - I can't duplicate

@HarryMuc
Copy link
Author

I guess 1-4 are all related to cfparser - not sure if it would be possible to use the integrated Lucee parser instead of cfparser?
4 - cfparser needs to support cflog text parsing?

@HarryMuc
Copy link
Author

Issue
Severity:INFO
Message code:UNUSED_LOCAL_VARIABLE
	File:D:\projekte_cf\contens\contens5\contens\core\scheduler\systemscheduler.cfc
	Column:0
	Line:354
		Message:Local variable sSecureFolder is not used in function checkCollections, consider removing it.
		Variable:'sSecureFolder' in function: checkCollections
		Expression:<cffunction name="checkCollections" access="public" returntype="struct" output="No" hint="checks collections">
		<cfset var sSecureFolder = expandPath("/#variables.stContens.applicationname#/_secure/


Total files:1
Total size 1227

Issue counts:1
UNUSED_LOCAL_VARIABLE:1

Total issues:1

@HarryMuc
Copy link
Author

	<cffunction name="checkCollections" access="public" returntype="struct" output="No" hint="checks collections">
		<cfset var sSecureFolder = expandPath("/#variables.stContens.applicationname#/_secure/collections/")>
		<cfset var stReturn = {}>
		<cfset var stResult = {}>
		<cfset var oAgents = getAppHelper().instanceFactory("contenscms.core.search.agent")>
		<cfset var lAgents = oAgents.getAgents()>
		<cfset var sAgent = "">
		<cfset var oAgent = "">

		<cfset stReturn.ok = true>
		<cfset stReturn.message = ''>
		<cfset stReturn.errormessage = ''>
		<cfset stReturn.data = {}>

		<cftry>
			<cfloop list="#lAgents#" index="sAgent">
				<!--- prevent parse errors --->
				<cflock name="checkCollection" type="exclusive" timeout="10">
					<cfset stResult = {}>

					<cfset oAgent = oAgents.getSearchAgent(sAgent)>

					<cfif isObject(oAgent)>
						<cfset stResult = oAgent.search(sTerm="dummytermtocheckforlocks", num=1)>
					</cfif>

					<cfset stReturn.data[sAgent] = stResult>

					<cfif stResult.ok>
						<cfset stReturn.message = 'Checked collections successfully.'>
					<cfelse>
						<cfset stReturn.ok = false>
						<cfset stReturn.errormessage = 'Error in Collection' & " > " & sAgent & " ">
					</cfif>
				</cflock>
			</cfloop>

			<cfcatch>
				<cflog file="content_errors" text="Please check the lucene collections in the folder #sSecureFolder# and manually remove the file 'write.lock'! #cfcatch.message#">
				<cfset stReturn.ok = false>
				<cfset stReturn.errormessage = cfcatch.message>
				<cfset stReturn.data = cfcatch>
			</cfcatch>
		</cftry>

		<cfif NOT stReturn.ok>
			<cfset stReturn.message = stReturn.errormessage>

			<!--- notify users about invalid collections --->
			<cfif structKeyExists(variables.stContens.search, "agentnotifications")>
				<cftry>
					<cfmail to="#variables.stContens.search.agentnotifications.notificationmailaddresses#" charset="UTF-8" from="#variables.stContens.search.agentnotifications.notificationmailsender#" subject="Agent notification: '#application.applicationname#'" timeout="30">Invalid search collection(s), switched to database fallback mode! Agent: #sAgent#</cfmail>
					<cfcatch></cfcatch>
				</cftry>
			</cfif>
		</cfif>

		<cfreturn stReturn>
	</cffunction>

@denuno
Copy link
Collaborator

denuno commented Jul 21, 2017

As far as using an engine's parser:

Engine parsers (like Lucee) have a different set of concerns than linters and IDEs have, which basically rules them out, as they're pure runtime (id est, one error at a time), while we (linters/IDE parsers) have to kind of swallow errors and keep on chugging to be at all useful.

That, and we want to know information that the engine parser doesn't care about-- variable names, what's scoped where, etc., etc..

@ryaneberly
Copy link
Contributor

@derrick13
I can't duplicate the issue with cflog text even with your full source example. It may be related to my local version of cfparser.

Does it work for you now that the dev trunk is using cfparser 2.4.10?

@HarryMuc
Copy link
Author

@ryaneberly I updated my version and now the log issue is gone.
Thanks for updating the dev trunk with the new cfparser version!

@ryaneberly
Copy link
Contributor

@derrick13 Thanks for confirming.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants