src/utils/annotateWithScopes.js/annotateWithScopes
export default function annotateWithScopes ( expression ) {
	let scope = new Scope( null, false );

	walk( expression, {
		enter ( node ) {
			if ( /Function/.test( node.type ) ) {
				if ( node.type === 'FunctionDeclaration' ) {
					scope.declarations.add( node.id.name );
				} else {
					node._scope = scope = new Scope( scope, false );
					if ( node.id ) scope.declarations.add( node.id.name );
				}

				node.params.forEach( param => {
					extractNames( param ).forEach( name => {
						scope.declarations.add( name );
					});
				});
			}

			else if ( /For(?:In|Of)Statement/.test( node.type ) ) {
				node._scope = scope = new Scope( scope, true );
			}

			else if ( node.type === 'BlockStatement' ) {
				node._scope = scope = new Scope( scope, true );
			}

			else if ( /(Function|Class|Variable)Declaration/.test( node.type ) ) {
				scope.addDeclaration( node );
			}
		},

		leave ( node ) {
			if ( node._scope ) {
				scope = scope.parent;
			}
		}
	});

	return scope;
}