diff options
Diffstat (limited to 'javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PhantomNodeLogic.java')
-rw-r--r-- | javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PhantomNodeLogic.java | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PhantomNodeLogic.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PhantomNodeLogic.java new file mode 100644 index 000000000..d17f76835 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/PhantomNodeLogic.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.printer.lexicalpreservation; + +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.observer.AstObserver; +import com.github.javaparser.ast.observer.AstObserverAdapter; +import com.github.javaparser.ast.type.UnknownType; + +import java.util.IdentityHashMap; +import java.util.Map; + +import static java.util.Collections.synchronizedMap; + +/** + * We want to recognize and ignore "phantom" nodes, like the fake type of variable in FieldDeclaration + */ +class PhantomNodeLogic { + + private static final int LEVELS_TO_EXPLORE = 3; + + private static final Map<Node, Boolean> isPhantomNodeCache = synchronizedMap(new IdentityHashMap<>()); + + private static final AstObserver cacheCleaner = new AstObserverAdapter() { + @Override + public void parentChange(Node observedNode, Node previousParent, Node newParent) { + isPhantomNodeCache.remove(observedNode); + } + }; + + static boolean isPhantomNode(Node node) { + if (isPhantomNodeCache.containsKey(node)) { + return isPhantomNodeCache.get(node); + } else { + if (node instanceof UnknownType) { + return true; + } + boolean res = (node.getParentNode().isPresent() && + !node.getParentNode().get().getRange().get().contains(node.getRange().get()) + || inPhantomNode(node, LEVELS_TO_EXPLORE)); + isPhantomNodeCache.put(node, res); + node.register(cacheCleaner); + return res; + } + } + + /** + * A node contained in a phantom node is also a phantom node. We limit how many levels up we check just for performance reasons. + */ + private static boolean inPhantomNode(Node node, int levels) { + return node.getParentNode().isPresent() && + (isPhantomNode(node.getParentNode().get()) + || inPhantomNode(node.getParentNode().get(), levels - 1)); + } +} |