Package me.pixodro.j2cpp.core.rewrite.changegenerator

Source Code of me.pixodro.j2cpp.core.rewrite.changegenerator.ASTModificationHelper

/*******************************************************************************
* Copyright (c) 2008, 2011 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences 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:
* Institute for Software - initial API and implementation
*******************************************************************************/
package me.pixodro.j2cpp.core.rewrite.changegenerator;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import me.pixodro.j2cpp.core.rewrite.ContainerNode;

import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.internal.core.dom.rewrite.ASTModification;
import org.eclipse.cdt.internal.core.dom.rewrite.ASTModification.ModificationKind;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;

public class ASTModificationHelper {
  private final ModificationScopeStack modificationStore;

  public ASTModificationHelper(final ModificationScopeStack stack) {
    modificationStore = stack;
  }

  public <T extends IASTNode> T[] createModifiedChildArray(final IASTNode parent, final T[] unmodifiedChildren, final Class<T> clazz, final NodeCommentMap commentMap) {
    final ArrayList<T> modifiedChildren = new ArrayList<T>(Arrays.asList(unmodifiedChildren));

    for (final ASTModification parentModification : modificationsForNode(parent)) {
      switch (parentModification.getKind()) {
      case APPEND_CHILD:
        IASTNode newNode = parentModification.getNewNode();
        final T appendedTNode = cast(newNode, clazz);
        if (appendedTNode != null) {
          modifiedChildren.add(appendedTNode);
        } else if (newNode instanceof ContainerNode) {
          final ContainerNode nodeContainer = (ContainerNode) newNode;
          for (final IASTNode currentNode : nodeContainer.getNodes()) {
            final T tnode = cast(currentNode, clazz);
            if (tnode != null) {
              modifiedChildren.add(tnode);
            }
          }
        }
        break;

      case INSERT_BEFORE:
        newNode = parentModification.getNewNode();
        if (newNode instanceof ContainerNode) {
          final ContainerNode contNode = (ContainerNode) newNode;
          for (final IASTNode node : contNode.getNodes()) {
            insertNode(clazz, modifiedChildren, parentModification, node);
          }
        } else {
          insertNode(clazz, modifiedChildren, parentModification, newNode);
        }
        break;

      case REPLACE:
        break;
      }
    }

    for (final T currentChild : unmodifiedChildren) {
      for (final ASTModification childModification : modificationsForNode(currentChild)) {
        try {
          final T newNode = cast(childModification.getNewNode(), clazz);
          switch (childModification.getKind()) {
          case REPLACE:
            if (newNode != null) {
              copyComments(newNode, currentChild, commentMap);
              modifiedChildren.add(modifiedChildren.indexOf(childModification.getTargetNode()), newNode);
            }
            modifiedChildren.remove(childModification.getTargetNode());
            break;
          case INSERT_BEFORE:
          case APPEND_CHILD:
            throw new UnhandledASTModificationException(childModification);
          }
        } catch (final ClassCastException e) {
          throw new UnhandledASTModificationException(childModification);
        }
      }
    }
    return modifiedChildren.toArray(newArrayInstance(clazz, modifiedChildren.size()));
  }

  private void copyComments(final IASTNode newNode, final IASTNode oldNode, final NodeCommentMap commentMap) {
    // Attach all the comments that is attached to oldNode to newNode
    final List<IASTComment> leadingComments = commentMap.getLeadingCommentsForNode(oldNode);
    for (final IASTComment comment : leadingComments) {
      commentMap.addLeadingCommentToNode(newNode, comment);
    }

    final List<IASTComment> trailingComments = commentMap.getTrailingCommentsForNode(oldNode);
    for (final IASTComment comment : trailingComments) {
      commentMap.addTrailingCommentToNode(newNode, comment);
    }

    final List<IASTComment> freestandingComments = commentMap.getFreestandingCommentsForNode(oldNode);
    for (final IASTComment comment : freestandingComments) {
      commentMap.addFreestandingCommentToNode(newNode, comment);
    }

    // Detach comments from oldNode (to avoid memory leak)
    final Map<IASTNode, List<IASTComment>> leadingMap = commentMap.getLeadingMap();
    leadingMap.remove(oldNode);

    final Map<IASTNode, List<IASTComment>> trailingMap = commentMap.getTrailingMap();
    trailingMap.remove(oldNode);

    final Map<IASTNode, List<IASTComment>> freestandingMap = commentMap.getFreestandingMap();
    freestandingMap.remove(oldNode);
  }

  private <T> void insertNode(final Class<T> clazz, final ArrayList<T> modifiedChildren, final ASTModification parentModification, final IASTNode newNode) {
    final T insertedTNode = cast(newNode, clazz);

    final int targetNodeIndex = modifiedChildren.indexOf(parentModification.getTargetNode());
    if (targetNodeIndex >= 0) {
      modifiedChildren.add(targetNodeIndex, insertedTNode);
    }
  }

  @SuppressWarnings("unchecked")
  private <T> T[] newArrayInstance(final Class<T> clazz, final int size) {
    return (T[]) Array.newInstance(clazz, size);
  }

  @SuppressWarnings("unchecked")
  private <T> T cast(final IASTNode node, final Class<T> clazz) {
    if (clazz.isInstance(node)) {
      return (T) node;
    }
    return null;
  }

  public List<ASTModification> modificationsForNode(final IASTNode targetNode) {
    List<ASTModification> modificationsForNode;
    if (modificationStore.getModifiedNodes().contains(targetNode)) {
      modificationsForNode = modificationStore.getModificationsForNode(targetNode);
    } else {
      modificationsForNode = Collections.emptyList();
    }
    return modificationsForNode;
  }

  public IASTInitializer getInitializer(final IASTDeclarator decl) {
    final IASTInitializer initializer = decl.getInitializer();

    if (initializer != null) {
      for (final ASTModification childModification : modificationsForNode(initializer)) {
        switch (childModification.getKind()) {
        case REPLACE:
          if (childModification.getNewNode() instanceof IASTInitializer) {
            return (IASTInitializer) childModification.getNewNode();
          } else if (childModification.getNewNode() == null) {
            return null;
          }
          throw new UnhandledASTModificationException(childModification);
        case INSERT_BEFORE:
          throw new UnhandledASTModificationException(childModification);

        case APPEND_CHILD:
          throw new UnhandledASTModificationException(childModification);
        }
      }
    } else {
      for (final ASTModification parentModification : modificationsForNode(decl)) {
        if (parentModification.getKind() == ModificationKind.APPEND_CHILD) {
          final IASTNode newNode = parentModification.getNewNode();
          if (newNode instanceof IASTInitializer) {
            return (IASTInitializer) newNode;
          }
        }
      }
    }
    return initializer;
  }

  @SuppressWarnings("unchecked")
  public <T extends IASTNode> T getNodeAfterReplacement(final T replacedNode) {
    final List<ASTModification> modifications = modificationsForNode(replacedNode);
    for (final ASTModification currentModification : modifications) {
      try {
        if (currentModification.getKind() == ModificationKind.REPLACE) {
          return (T) currentModification.getNewNode();
        }
      } catch (final ClassCastException e) {
        throw new UnhandledASTModificationException(currentModification);
      }
    }
    return replacedNode;
  }
}
TOP

Related Classes of me.pixodro.j2cpp.core.rewrite.changegenerator.ASTModificationHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.