blob: d17f768352d6cf62830dda14b6ccbdbb3c8cfc37 [file] [log] [blame]
/*
* 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));
}
}