/******************************************************************************* * Copyright (c) 2011 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.ibm.wala.cast.js.ipa.callgraph.correlations.extraction; import static com.ibm.wala.cast.tree.CAstNode.ASSIGN; import static com.ibm.wala.cast.tree.CAstNode.BLOCK_STMT; import static com.ibm.wala.cast.tree.CAstNode.DECL_STMT; import static com.ibm.wala.cast.tree.CAstNode.EACH_ELEMENT_GET; import static com.ibm.wala.cast.tree.CAstNode.EMPTY; import static com.ibm.wala.cast.tree.CAstNode.LABEL_STMT; import static com.ibm.wala.cast.tree.CAstNode.LOCAL_SCOPE; import static com.ibm.wala.cast.tree.CAstNode.VAR; import java.util.Collections; import java.util.List; import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstNode; import com.ibm.wala.cast.tree.pattern.Alt; import com.ibm.wala.cast.tree.pattern.AnyNode; import com.ibm.wala.cast.tree.pattern.NodeOfKind; import com.ibm.wala.cast.tree.pattern.SomeConstant; import com.ibm.wala.cast.tree.pattern.SubtreeOfKind; /** * A policy telling a {@link ClosureExtractor} to extract the body of every for-in loop. * * NB: This policy matches on Rhino-specific encodings of for-in loops and hence is inherently non-portable. * * @author mschaefer * */ public class ForInBodyExtractionPolicy extends ExtractionPolicy { public static final ForInBodyExtractionPolicy INSTANCE = new ForInBodyExtractionPolicy(); public static final ExtractionPolicyFactory FACTORY = new ExtractionPolicyFactory() { @Override public ExtractionPolicy createPolicy(CAstEntity entity) { return INSTANCE; } }; private ForInBodyExtractionPolicy() {} @Override public List<ExtractionRegion> extract(CAstNode node) { SomeConstant loopVar = new SomeConstant(); /* * matches Rhino 1.7.3 encoding of for-in loop bodies: * * BLOCK_STMT * decl/assign of loop variable * optional SCOPE * <loopBody> */ if(new NodeOfKind(BLOCK_STMT, new Alt(new NodeOfKind(DECL_STMT, loopVar, new SubtreeOfKind(EACH_ELEMENT_GET)), new NodeOfKind(ASSIGN, new NodeOfKind(VAR, loopVar), new SubtreeOfKind(EACH_ELEMENT_GET))), new AnyNode(), new NodeOfKind(BLOCK_STMT, new SubtreeOfKind(LABEL_STMT), new SubtreeOfKind(EMPTY))).matches(node)) { List<String> parms = Collections.singletonList((String)loopVar.getLastMatch()); if(node.getChild(1).getKind() == LOCAL_SCOPE) { return Collections.<ExtractionRegion>singletonList(new TwoLevelExtractionRegion(1, 2, 0, -1, parms, Collections.<String>emptyList())); } else { return Collections.singletonList(new ExtractionRegion(1, 2, parms, Collections.<String>emptyList())); } } /* matches Rhino < 1.7.3 encoding of for-in loop bodies: * * BLOCK_STMT * ASSIGN * VAR <loopVar> * EACH_ELEMENT_GET * VAR <forin_tmp> * <loopBody> */ if(new NodeOfKind(BLOCK_STMT, new NodeOfKind(ASSIGN, new NodeOfKind(VAR, loopVar), new SubtreeOfKind(EACH_ELEMENT_GET)), new AnyNode()).matches(node)) { List<String> parms = Collections.singletonList((String)loopVar.getLastMatch()); return Collections.singletonList(new ExtractionRegion(1, 2, parms, Collections.<String>emptyList())); } return null; } }