Package com.puppetlabs.geppetto.pp.dsl.linking

Source Code of com.puppetlabs.geppetto.pp.dsl.linking.PPObjectAtOffsetHelper

/**
* Copyright (c) 2013 Puppet Labs, Inc. and other contributors, as listed below.
* 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:
*   Puppet Labs
*/
package com.puppetlabs.geppetto.pp.dsl.linking;

import java.util.List;

import com.puppetlabs.geppetto.pp.dsl.adapters.CrossReferenceAdapterFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.AbstractRule;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.GrammarUtil;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.parser.IParseResult;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.util.ITextRegion;
import org.eclipse.xtext.util.TextRegion;

/**
* @author Jan Koehnlein - Initial contribution and API
*/
public class PPObjectAtOffsetHelper {

  /**
   * TOOO: USE THIS
   *
   * @param a
   *            node (possibly null)
   * @return if the given node is part of a cross reference this method returns the node pointing to the
   *         {@link CrossReference} <code>null</code> if
   *         the passed node was a null reference or if the passed node is
   *         not part of a cross reference.
   * @since 2.1
   */
  private INode findCrossReferenceNode(INode node) {
    if(node == null)
      return null;
    EObject eObj = NodeModelUtils.findActualSemanticObjectFor(node);
    List<IEObjectDescription> crossReferences = CrossReferenceAdapterFactory.eINSTANCE.get(eObj);
    if(crossReferences != null && crossReferences.size() > 0)
      return node;

    // if (node.getGrammarElement() instanceof CrossReference)
    // return node;
    while(node.getGrammarElement() != null && isElementOfDatatypeRule(node.getGrammarElement())) {
      node = node.getParent();
      eObj = NodeModelUtils.findActualSemanticObjectFor(node);
      crossReferences = CrossReferenceAdapterFactory.eINSTANCE.get(eObj);
      if(crossReferences != null && crossReferences.size() > 0)
        return node;

      // if (node.getGrammarElement() instanceof CrossReference)
      // return node;
    }
    return null;
  }

  /**
   * TODO: USE THIS
   *
   * @param node
   *            a node with an associated {@link CrossReference} grammar element.
   * @return the {@link EObject} referenced by this node
   * @since 2.1
   */
  public List<IEObjectDescription> getCrossReferencedElement(INode node) {
    EObject eObj = NodeModelUtils.findActualSemanticObjectFor(node);
    List<IEObjectDescription> crossReferences = CrossReferenceAdapterFactory.eINSTANCE.get(eObj);
    if(crossReferences == null || crossReferences.size() < 1)
      throw new IllegalArgumentException("Passed node not a pp cross reference node.");

    // if (!(node.getGrammarElement() instanceof CrossReference))
    // throw new IllegalArgumentException("Passed node not a cross reference node.");
    return resolveCrossReferencedElement(node);
  }

  /**
   * TODO: Use this
   *
   * @since 2.1
   */
  public INode getCrossReferenceNode(XtextResource resource, ITextRegion region) {
    IParseResult parseResult = resource.getParseResult();
    if(parseResult != null && parseResult.getRootNode() != null) {
      ILeafNode leaf = NodeModelUtils.findLeafNodeAtOffset(parseResult.getRootNode(), region.getOffset());
      INode crossRefNode = findCrossReferenceNode(leaf);
      // if not a cross reference position and the cursor is at the beginning of a node try the previous one.
      if(crossRefNode == null && leaf != null && region.getLength() == 0 &&
          leaf.getOffset() == region.getOffset()) {
        leaf = NodeModelUtils.findLeafNodeAtOffset(parseResult.getRootNode(), region.getOffset() - 1);
        return findCrossReferenceNode(leaf);
      }
      else if(crossRefNode != null &&
          crossRefNode.getOffset() + crossRefNode.getLength() >= region.getOffset() + region.getLength()) {
        return crossRefNode;
      }
    }
    return null;
  }

  // protected EObject internalResolveElementAt(XtextResource resource, int offset, boolean containment) {
  // EObject crossRef = resolveCrossReferencedElementAt(resource, offset);
  // if(crossRef != null)
  // return crossRef;
  // IParseResult parseResult = resource.getParseResult();
  // if(parseResult != null && parseResult.getRootNode() != null) {
  // ILeafNode leaf = NodeModelUtils.findLeafNodeAtOffset(parseResult.getRootNode(), offset);
  // if(leaf != null && leaf.isHidden() && leaf.getOffset() == offset) {
  // leaf = NodeModelUtils.findLeafNodeAtOffset(parseResult.getRootNode(), offset - 1);
  // }
  // if(leaf != null) {
  // return NodeModelUtils.findActualSemanticObjectFor(leaf);
  // }
  // }
  // return null;
  // }

  /**
   * USE THIS
   *
   * @since 2.1
   */
  protected boolean isElementOfDatatypeRule(final EObject grammarElement) {
    final AbstractRule rule = EcoreUtil2.getContainerOfType(grammarElement, AbstractRule.class);
    return GrammarUtil.isDatatypeRule(rule);
  }

  /**
   * TODO: USE THIS
   *
   * @param node
   * @return
   */
  protected List<IEObjectDescription> resolveCrossReferencedElement(INode node) {
    EObject referenceOwner = NodeModelUtils.findActualSemanticObjectFor(node);
    if(referenceOwner != null)
      return CrossReferenceAdapterFactory.eINSTANCE.get(referenceOwner);

    // EReference crossReference = GrammarUtil.getReference((CrossReference) node.getGrammarElement(),
    // referenceOwner.eClass());
    // if (!crossReference.isMany()) {
    // return (EObject) referenceOwner.eGet(crossReference);
    // }
    // List<?> listValue = (List<?>) referenceOwner.eGet(crossReference);
    // List<INode> nodesForFeature = NodeModelUtils.findNodesForFeature(referenceOwner, crossReference);
    // int currentIndex = 0;
    // for (INode nodeForFeature : nodesForFeature) {
    // if (currentIndex >= listValue.size())
    // return null;
    // if (nodeForFeature.getTotalOffset() <= node.getTotalOffset()
    // && nodeForFeature.getTotalEndOffset() >= node.getTotalEndOffset())
    // return (EObject) listValue.get(currentIndex);
    // currentIndex++;
    // }

    return null;
  }

  /**
   * TODO: USE THIS
   *
   * @return the cross referenced EObject under, right or left to the cursor (in that order) or <code>null</code> if
   *         there is no cross referenced
   *         object next to the offset.
   */
  public List<IEObjectDescription> resolveCrossReferencedElementAt(XtextResource resource, int offset) {
    INode node = getCrossReferenceNode(resource, new TextRegion(offset, 0));
    if(node != null)
      return getCrossReferencedElement(node);
    return null;
  }

  // public EObject resolveElementAt(XtextResource resource, int offset) {
  // return internalResolveElementAt(resource, offset, true);
  // }

}
TOP

Related Classes of com.puppetlabs.geppetto.pp.dsl.linking.PPObjectAtOffsetHelper

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.