Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] Add Rewrite Events #871

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/

package net.sourceforge.pmd.autofix.rewriteevents;

import java.util.Objects;

import net.sourceforge.pmd.lang.ast.Node;

/**
* <p>
* Describe a modification over a {@link Node} so as to be able to track changes over it.
* </p>
* <p>
* The modification is described by specifying the node on which the modification has occurred ({@code parentNode}),
* the old child node ({@code oldChildNode}), the new child node ({@code newChildNode}) and the index of the
* child node being modified ({@code childNodeIndex}).
* </p>
* <p>
* The {@code rewriteEventType} is obtained based on the provided values for
* {@code oldChildNode} and {@code newChildNode} (which may be null).
* </p>
*/
public class RewriteEvent {
private final Node parentNode;
private final Node oldChildNode;
private final Node newChildNode;
private final int childNodeIndex;
private final RewriteEventType rewriteEventType;

public RewriteEvent(final Node parentNode,
final Node oldChildNode,
final Node newChildNode,
final int childNodeIndex) {
this.parentNode = Objects.requireNonNull(parentNode);
this.oldChildNode = oldChildNode;
this.newChildNode = newChildNode;
this.childNodeIndex = requireNonNegative(childNodeIndex);
this.rewriteEventType = grabRewriteEventType();
}

private RewriteEventType grabRewriteEventType() {
if (Objects.equals(oldChildNode, newChildNode)) {
throw new IllegalArgumentException("Cannot generate a rewrite event with both child nodes being equal");
} else if (oldChildNode == null) { // newChildNode not null as they are not equal
return RewriteEventType.INSERT;
} else if (newChildNode == null) { // oldChildNode not null as they are not equal
return RewriteEventType.REMOVE;
} else { // oldChildNode & newChildNode are both not null & not equal
return RewriteEventType.REPLACE;
}
}

private int requireNonNegative(final int n) {
if (n < 0) {
throw new IllegalArgumentException(String.format("n <%d> is lower than 0", n));
}
return n;
}

public RewriteEventType getRewriteEventType() {
return rewriteEventType;
}

public Node getParentNode() {
return parentNode;
}

public Node getOldChildNode() {
return oldChildNode;
}

public Node getNewChildNode() {
return newChildNode;
}

public int getChildNodeIndex() {
return childNodeIndex;
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final RewriteEvent rewriteEvent = (RewriteEvent) o;
return childNodeIndex == rewriteEvent.childNodeIndex
&& rewriteEventType == rewriteEvent.rewriteEventType
&& Objects.equals(parentNode, rewriteEvent.parentNode)
&& Objects.equals(oldChildNode, rewriteEvent.oldChildNode)
&& Objects.equals(newChildNode, rewriteEvent.newChildNode);
}

@Override
public int hashCode() {
return Objects.hash(rewriteEventType, parentNode, oldChildNode, newChildNode, childNodeIndex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/

package net.sourceforge.pmd.autofix.rewriteevents;

import net.sourceforge.pmd.lang.ast.Node;

/**
* Factory of {@link RewriteEvent} objects.
*/
public abstract class RewriteEventFactory {
/**
* @param parentNode The parent node over which the modification is occurring.
* @param newChildNode The new child node value being inserted.
* @param childIndex The index of the child node being modified.
* @return A new {@link RewriteEvent} of type {@code INSERT} containing the given values.
*/
public static RewriteEvent newInsertRewriteEvent(final Node parentNode, final Node newChildNode, final int childIndex) {
return new RewriteEvent(parentNode, null, newChildNode, childIndex);
}

/**
* @param parentNode The parent node over which the modification is occurring.
* @param oldChildNode The old child node value being removed.
* @param childIndex The index of the child node being modified.
* @return A new {@link RewriteEvent} of type {@code REMOVE} containing the given values.
*/
public static RewriteEvent newRemoveRewriteEvent(final Node parentNode, final Node oldChildNode, final int childIndex) {
return new RewriteEvent(parentNode, oldChildNode, null, childIndex);
}

/**
* @param parentNode The parent node over which the modification is occurring.
* @param oldChildNode The new child node value being removed.
* @param newChildNode The new child node value being inserted.
* @param childIndex The index of the child node being modified.
* @return A new {@link RewriteEvent} of type {@code REPLACE} containing the given values.
*/
public static RewriteEvent newReplaceRewriteEvent(final Node parentNode, final Node oldChildNode, final Node newChildNode, final int childIndex) {
return new RewriteEvent(parentNode, oldChildNode, newChildNode, childIndex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/

package net.sourceforge.pmd.autofix.rewriteevents;

/**
* <p>
* Enum describing all possible types of {@link RewriteEvent}s.
* </p>
* <p>
* Each type holds a <strong>valid*</strong> index position, so as to ensure that one can build arrays
* using these types for accessing its elements.
* </p>
* <p>
* <strong>*valid</strong> means that each type holds a unique index in the range
* {@code [0, RewriteEventType.values() - 1]}.
* </p>
*/
public enum RewriteEventType {
INSERT(0), REMOVE(1), REPLACE(2);

private final int index;

RewriteEventType(final int index) {
this.index = index;
}

public int getIndex() {
return index;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/

package net.sourceforge.pmd.autofix.rewriteevents;

import net.sourceforge.pmd.lang.ast.Node;

/**
* All classes implementing this interface should
* record all modifications that occur over the children of parent node.
*/
public interface RewriteEventsRecorder {

/**
* Record a remove operation over the given {@code parentNode}.
*
* @param parentNode The node whose child is being removed.
* @param oldChildNode The child node being removed.
* @param childIndex The index of the child node being removed.
*/
void recordRemove(Node parentNode, Node oldChildNode, int childIndex);

/**
* Record an insert operation over the given {@code parentNode}.
*
* @param parentNode The node on which a new child is being inserted.
* @param newChildNode The child node being inserted.
* @param childIndex The index where the new child node is being inserted.
*/
void recordInsert(Node parentNode, Node newChildNode, int childIndex);

/**
* Record a replace operation over the given {@code parentNode}.
*
* @param parentNode The node whose child is being replaced.
* @param oldChildNode The child node being replaced.
* @param newChildNode The new child node that will replace the {@code oldChildNode}.
* @param childIndex The index of the child node being replaced.
*/
void recordReplace(Node parentNode, Node oldChildNode, Node newChildNode, int childIndex);

/**
* @return {@code true} if this instance holds any rewrite event; {@code false} otherwise.
*/
boolean hasRewriteEvents();

/**
* @return A copy of all the {@link RewriteEvent}s held by this instance (may be null).
*/
RewriteEvent[] getRewriteEvents();
}
Loading