Copyright (c) 2013 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2013 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.eclipse.jdt.internal.core.dom; import java.util.List; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.ArrayCreation; import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; @SuppressWarnings("rawtypes") public class SourceRangeVerifier extends ASTVisitor { public static boolean DEBUG = false; public static boolean DEBUG_THROW = false; private StringBuffer bugs;
Verifies proper node nesting as specified in ASTParser.setKind(int):

Source ranges nest properly: the source range for a child is always within the source range of its parent, and the source ranges of sibling nodes never overlap.

Params:
  • node –
Returns:null if everything is OK; a list of errors otherwise
/** * Verifies proper node nesting as specified in {@link ASTParser#setKind(int)}: * <p> * Source ranges nest properly: the source range for a child is always * within the source range of its parent, and the source ranges of sibling * nodes never overlap. * </p> * * @param node * @return <code>null</code> if everything is OK; a list of errors otherwise */
public String process(ASTNode node) { StringBuffer buffer = new StringBuffer(); this.bugs = buffer; node.accept(this); this.bugs = null; if (buffer.length() == 0) return null; return buffer.toString(); } @Override public boolean preVisit2(ASTNode node) { ASTNode previous = null; List properties = node.structuralPropertiesForType(); for (int i = 0; i < properties.size(); i++) { StructuralPropertyDescriptor property = (StructuralPropertyDescriptor) properties.get(i); if (property.isChildProperty()) { ASTNode child = (ASTNode) node.getStructuralProperty(property); if (child != null) { boolean ok = checkChild(node, previous, child); if (ok) { previous = child; } else { return false; } } } else if (property.isChildListProperty()) { List children = (List) node.getStructuralProperty(property); for (int j= 0; j < children.size(); j++) { ASTNode child = (ASTNode) children.get(j); boolean ok = checkChild(node, previous, child); if (ok) { previous = child; } else { return false; } } } } return true; } private boolean checkChild(ASTNode parent, ASTNode previous, ASTNode child) { if ((parent.getFlags() & (ASTNode.RECOVERED | ASTNode.MALFORMED)) != 0 || (child.getFlags() & (ASTNode.RECOVERED | ASTNode.MALFORMED)) != 0) return false; int parentStart = parent.getStartPosition(); int parentEnd = parentStart + parent.getLength(); int childStart = child.getStartPosition(); int childEnd = childStart + child.getLength(); if (previous != null) { // Turn a blind eye on a known problem ... see https://bugs.eclipse.org/391894#c4 if (child.getLocationInParent() == ArrayCreation.DIMENSIONS_PROPERTY) return false; int previousStart = previous.getStartPosition(); int previousEnd = previousStart + previous.getLength(); if (childStart < previousEnd) { String bug = "- parent [" + parentStart + ", " + parentEnd + "] " + parent.getClass().getName() + '\n' //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + " previous [" + previousStart + ", " + previousEnd + "] " + previous.getClass().getName() + '\n'//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + " " + child.getLocationInParent().getId() + " [" + childStart + ", " + childEnd + "] " + child.getClass().getName() + '\n'; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ this.bugs.append(bug); } } if (!(parentStart <= childStart && childEnd <= parentEnd)) { String bug = "- parent [" + parentStart + ", " + parentEnd + "] " + parent.getClass().getName() + '\n' //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + " " + child.getLocationInParent().getId() + " [" + childStart + ", " + childEnd + "] " + child.getClass().getName() + '\n'; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ this.bugs.append(bug); } return true; } }