@ -3,6 +3,8 @@ import checkForComputedKeys from '../utils/checkForComputedKeys';
import { walk } from 'estree-walker' ;
import { walk } from 'estree-walker' ;
import { Validator } from '../../' ;
import { Validator } from '../../' ;
import { Node } from '../../../interfaces' ;
import { Node } from '../../../interfaces' ;
import walkThroughTopFunctionScope from '../../../utils/walkThroughTopFunctionScope' ;
import isThisGetCallExpression from '../../../utils/isThisGetCallExpression' ;
export default function helpers ( validator : Validator , prop : Node ) {
export default function helpers ( validator : Validator , prop : Node ) {
if ( prop . value . type !== 'ObjectExpression' ) {
if ( prop . value . type !== 'ObjectExpression' ) {
@ -18,45 +20,24 @@ export default function helpers(validator: Validator, prop: Node) {
prop . value . properties . forEach ( ( prop : Node ) = > {
prop . value . properties . forEach ( ( prop : Node ) = > {
if ( ! /FunctionExpression/ . test ( prop . value . type ) ) return ;
if ( ! /FunctionExpression/ . test ( prop . value . type ) ) return ;
let lexicalDepth = 0 ;
let usesArguments = false ;
let usesArguments = false ;
walk ( prop . value . body , {
walkThroughTopFunctionScope ( prop . value . body , ( node : Node ) = > {
enter ( node : Node ) {
if ( isThisGetCallExpression ( node ) && ! node . callee . property . computed ) {
if ( /^Function/ . test ( node . type ) ) {
validator . error (
lexicalDepth += 1 ;
` Cannot use this.get(...) — it must be passed into the helper function as an argument ` ,
} else if ( lexicalDepth === 0 ) {
node . start
// handle special case that's caused some people confusion — using `this.get(...)` instead of passing argument
) ;
// TODO do the same thing for computed values?
}
if (
node . type === 'CallExpression' &&
if ( node . type === 'ThisExpression' ) {
node . callee . type === 'MemberExpression' &&
validator . error (
node . callee . object . type === 'ThisExpression' &&
` Helpers should be pure functions — they do not have access to the component instance and cannot use 'this'. Did you mean to put this in 'methods'? ` ,
node . callee . property . name === 'get' &&
node . start
! node . callee . property . computed
) ;
) {
} else if ( node . type === 'Identifier' && node . name === 'arguments' ) {
validator . error (
usesArguments = true ;
` Cannot use this.get(...) — it must be passed into the helper function as an argument ` ,
}
node . start
) ;
}
if ( node . type === 'ThisExpression' ) {
validator . error (
` Helpers should be pure functions — they do not have access to the component instance and cannot use 'this'. Did you mean to put this in 'methods'? ` ,
node . start
) ;
} else if ( node . type === 'Identifier' && node . name === 'arguments' ) {
usesArguments = true ;
}
}
} ,
leave ( node : Node ) {
if ( /^Function/ . test ( node . type ) ) {
lexicalDepth -= 1 ;
}
} ,
} ) ;
} ) ;
if ( prop . value . params . length === 0 && ! usesArguments ) {
if ( prop . value . params . length === 0 && ! usesArguments ) {