/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Zend Technologies
*******************************************************************************/
package org2.eclipse.php.internal.core.ast.rewrite;
import org2.eclipse.php.internal.core.ast.nodes.ASTNode;
import org2.eclipse.php.internal.core.ast.nodes.Program;
/**
* An object for computing adjusted source ranges for AST nodes that are being
* replaced or deleted.
* <p>
* For example, a refactoring like inline method may choose to replace calls to
* the method but leave intact any comments immediately preceding the calls. On
* the other hand, a refactoring like extract method may choose to extract not
* only the nodes for the selected code but also any comments preceding or
* following them.
* </p>
* <p>
* Clients should subclass if they need to influence the the source range to be
* affected when replacing or deleting a particular node. An instance of the
* subclass should be registered with
* {@link ASTRewrite#setTargetSourceRangeComputer(TargetSourceRangeComputer)}.
* During a call to
* {@link ASTRewrite#rewriteAST(org.eclipse.jface.text.IDocument, java.util.Map)}
* , the {@link #computeSourceRange(ASTNode)} method on this object will be used
* to compute the source range for a node being deleted or replaced.
* </p>
*
* @since 3.1
*/
public class TargetSourceRangeComputer {
/**
* Reified source range. Instances are "value" object (cannot be
* modified).
*
* @since 3.1
*/
public static final class SourceRange {
/**
* 0-based character index, or <code>-1</code> if no source position
* information is known.
*/
private int startPosition;
/**
* (possibly 0) length, or <code>0</code> if no source position
* information is known.
*/
private int length;
/**
* Creates a new source range.
*
* @param startPosition
* the 0-based character index, or <code>-1</code> if no
* source position information is known
* @param length
* the (possibly 0) length, or <code>0</code> if no source
* position information is known
*/
public SourceRange(int startPosition, int length) {
this.startPosition = startPosition;
this.length = length;
}
/**
* Returns the start position.
*
* @return the 0-based character index, or <code>-1</code> if no source
* position information is known
*/
public int getStartPosition() {
return this.startPosition;
}
/**
* Returns the source length.
*
* @return a (possibly 0) length, or <code>0</code> if no source
* position information is known
*/
public int getLength() {
return this.length;
}
}
/**
* Creates a new target source range computer.
*/
public TargetSourceRangeComputer() {
// do nothing
}
/**
* Returns the target source range of the given node. Unlike
* {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()}, the
* extended source range may include comments and whitespace immediately
* before or after the normal source range for the node.
* <p>
* The returned source ranges must satisfy the following conditions:
* <dl>
* <li>no two source ranges in an AST may be overlapping</li>
* <li>a source range of a parent node must fully cover the source ranges of
* its children</li>
* </dl>
* </p>
* <p>
* The default implementation uses
* {@link CompilationUnit#getExtendedStartPosition(ASTNode)} and
* {@link CompilationUnit#getExtendedLength(ASTNode)} to compute the target
* source range. Clients may override or extend this method to expand or
* contract the source range of the given node. The resulting source range
* must cover at least the original source range of the node.
* </p>
*
* @param node
* the node with a known source range in the compilation unit
* being rewritten
* @return the exact source range in the compilation unit being rewritten
* that should be replaced (or deleted)
*/
public SourceRange computeSourceRange(ASTNode node) {
ASTNode root = node.getProgramRoot();
if (root instanceof Program) {
Program cu = (Program) root;
return new SourceRange(cu.getExtendedStartPosition(node), cu
.getExtendedLength(node));
}
return new SourceRange(node.getStart(), node.getLength());
}
}