1 /* 2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javac.comp; 27 28 import com.sun.tools.javac.code.Symbol; 29 import com.sun.tools.javac.code.Symbol.VarSymbol; 30 import com.sun.tools.javac.tree.JCTree; 31 import com.sun.tools.javac.tree.TreeScanner; 32 import com.sun.tools.javac.util.List; 33 34 import java.util.HashSet; 35 import java.util.LinkedHashSet; 36 import java.util.SequencedSet; 37 import java.util.Set; 38 39 import static com.sun.tools.javac.code.Kinds.Kind.MTH; 40 import static com.sun.tools.javac.code.Kinds.Kind.VAR; 41 42 /** 43 * A visitor which collects the set of local variables "captured" by a given tree. 44 */ 45 public class CaptureScanner extends TreeScanner { 46 47 /** 48 * The tree under analysis. 49 */ 50 private final JCTree tree; 51 52 /** 53 * The set of local variable declarations encountered in the tree under analysis. 54 */ 55 private final Set<Symbol.VarSymbol> seenVars = new HashSet<>(); 56 57 /** 58 * The set of captured local variables accessed from within the tree under analysis. 59 */ 60 private final SequencedSet<VarSymbol> fvs = new LinkedHashSet<>(); 61 62 public CaptureScanner(JCTree ownerTree) { 63 this.tree = ownerTree; 64 } 65 66 @Override 67 public void visitIdent(JCTree.JCIdent tree) { 68 Symbol sym = tree.sym; 69 if (sym.kind == VAR && sym.owner.kind == MTH) { 70 Symbol.VarSymbol vsym = (Symbol.VarSymbol) sym; 71 if (vsym.getConstValue() == null && !seenVars.contains(vsym)) { 72 addFreeVar(vsym); 73 } 74 } 75 } 76 77 /** 78 * Add free variable to fvs list unless it is already there. 79 */ 80 protected void addFreeVar(Symbol.VarSymbol v) { 81 fvs.add(v); 82 } 83 84 @Override 85 public void visitVarDef(JCTree.JCVariableDecl tree) { 86 if (tree.sym.owner.kind == MTH) { 87 seenVars.add(tree.sym); 88 } 89 super.visitVarDef(tree); 90 } 91 92 /** 93 * Obtains the list of captured local variables in the tree under analysis. 94 */ 95 public List<Symbol.VarSymbol> analyzeCaptures() { 96 scan(tree); 97 return List.from(fvs); 98 } 99 }