/* * Copyright 2017-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.jvm.java.abi.source; import com.facebook.buck.util.liteinfersupport.Nullable; import com.facebook.buck.util.liteinfersupport.Preconditions; import com.sun.source.tree.Tree; import com.sun.source.util.TreePath; import com.sun.source.util.TreeScanner; import com.sun.source.util.Trees; import javax.lang.model.element.Element; import javax.lang.model.type.TypeMirror; /** * A {@link TreeScanner} that keeps track of the following as it is scanning: * * <ul> * <li>The {@link TreePath} from the {@link com.sun.source.tree.CompilationUnitTree} * <li>The nearest {@link Element} that encloses the current {@link Tree} * </ul> */ class TreeContextScanner<R, P> extends TreeScanner<R, P> { private final Trees trees; @Nullable private TreePath currentPath; @Nullable private Element enclosingElement; public TreeContextScanner(Trees trees) { this.trees = trees; } protected final TreePath getCurrentPath() { return Preconditions.checkNotNull(currentPath); } /** Returns the {@link Element} that encloses the current tree path. */ protected final Element getEnclosingElement() { return Preconditions.checkNotNull(enclosingElement); } /** * Returns the {@link Element} for the type of the current tree. (Equivalent to {@code * getCurrentType().asElement()} when the current tree represents a type for which there is an * element.) */ @Nullable protected final Element getCurrentElement() { return trees.getElement(getCurrentPath()); } @Nullable protected final TypeMirror getCurrentType() { return trees.getTypeMirror(getCurrentPath()); } @Override @Nullable public R scan(Tree tree, @Nullable P p) { if (tree == null) { return null; } TreePath previousPath = currentPath; Element previousEnclosingElement = enclosingElement; currentPath = new TreePath(currentPath, tree); switch (tree.getKind()) { case ANNOTATION_TYPE: case CLASS: case COMPILATION_UNIT: case ENUM: case INTERFACE: case METHOD: case VARIABLE: case TYPE_PARAMETER: enclosingElement = Preconditions.checkNotNull(trees.getElement(currentPath)); break; // $CASES-OMITTED$ default: break; } try { // This super call will actually visit the tree, now with all the context set up return super.scan(tree, p); } finally { currentPath = previousPath; enclosingElement = previousEnclosingElement; } } }