Package org.eclipse.php.internal.core.typeinference.evaluators

Source Code of org.eclipse.php.internal.core.typeinference.evaluators.IteratorTypeGoalEvaluator

package org.eclipse.php.internal.core.typeinference.evaluators;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.dltk.ast.references.SimpleReference;
import org.eclipse.dltk.core.*;
import org.eclipse.dltk.evaluation.types.MultiTypeType;
import org.eclipse.dltk.ti.GoalState;
import org.eclipse.dltk.ti.ISourceModuleContext;
import org.eclipse.dltk.ti.goals.ExpressionTypeGoal;
import org.eclipse.dltk.ti.goals.GoalEvaluator;
import org.eclipse.dltk.ti.goals.IGoal;
import org.eclipse.dltk.ti.types.IEvaluatedType;
import org.eclipse.php.internal.core.Logger;
import org.eclipse.php.internal.core.compiler.ast.nodes.PHPDocBlock;
import org.eclipse.php.internal.core.compiler.ast.nodes.PHPDocTag;
import org.eclipse.php.internal.core.compiler.ast.nodes.PHPMethodDeclaration;
import org.eclipse.php.internal.core.typeinference.GeneratorClassType;
import org.eclipse.php.internal.core.typeinference.IModelAccessCache;
import org.eclipse.php.internal.core.typeinference.PHPClassType;
import org.eclipse.php.internal.core.typeinference.PHPModelUtils;
import org.eclipse.php.internal.core.typeinference.context.IModelCacheContext;
import org.eclipse.php.internal.core.typeinference.context.MethodContext;
import org.eclipse.php.internal.core.typeinference.evaluators.phpdoc.PHPDocClassVariableEvaluator;
import org.eclipse.php.internal.core.typeinference.goals.IteratorTypeGoal;
import org.eclipse.php.internal.core.typeinference.goals.MethodElementReturnTypeGoal;
import org.eclipse.php.internal.core.typeinference.goals.phpdoc.PHPDocMethodReturnTypeGoal;

public class IteratorTypeGoalEvaluator extends GoalEvaluator {

  private IEvaluatedType result;

  public IteratorTypeGoalEvaluator(IGoal goal) {
    super(goal);
  }

  public IGoal[] init() {
    IteratorTypeGoal typedGoal = (IteratorTypeGoal) goal;
    return new IGoal[] { new ExpressionTypeGoal(goal.getContext(),
        typedGoal.getExpression()) };
  }

  public Object produceResult() {
    return result;
  }

  public IGoal[] subGoalDone(IGoal subgoal, Object result, GoalState state) {
    IModelAccessCache cache = null;
    if (goal.getContext() instanceof IModelCacheContext) {
      cache = (IModelAccessCache) ((IModelCacheContext) goal.getContext())
          .getCache();
    }
    if (state != GoalState.RECURSIVE) {
      if (result instanceof GeneratorClassType) {
        MultiTypeType type = new MultiTypeType();
        type.getTypes()
            .addAll(((GeneratorClassType) result).getTypes());
        this.result = type;
        return IGoal.NO_GOALS;
      } else if (result instanceof PHPClassType) {
        if (subgoal instanceof ExpressionTypeGoal) {
          ISourceModule sourceModule = ((ISourceModuleContext) subgoal
              .getContext()).getSourceModule();
          PHPClassType classType = (PHPClassType) result;
          List<IGoal> subGoals = new LinkedList<IGoal>();
          try {
            IType[] types = PHPModelUtils.getTypes(
                classType.getTypeName(), sourceModule, 0,
                cache, null);
            for (IType type : types) {
              IType[] superTypes = PHPModelUtils.getSuperClasses(
                  type,
                  cache == null ? null : cache
                      .getSuperTypeHierarchy(type, null));

              if (subgoal.getContext() instanceof MethodContext) {

                MethodContext methodContext = (MethodContext) subgoal
                    .getContext();

                if (isArrayType(methodContext, type)) {
                  MultiTypeType mType = new MultiTypeType();
                  mType.addType((IEvaluatedType) result);
                  this.result = mType;
                  return IGoal.NO_GOALS;
                }
              }

              if (isImplementedIterator(superTypes)) {
                subGoals.add(new MethodElementReturnTypeGoal(
                    subgoal.getContext(),
                    new IType[] { type }, "current")); //$NON-NLS-1$
                subGoals.add(new PHPDocMethodReturnTypeGoal(
                    subgoal.getContext(),
                    new IType[] { type }, "current")); //$NON-NLS-1$
              }
            }
            if (subGoals.size() == 0) {
              MultiTypeType mType = new MultiTypeType();
              mType.addType((IEvaluatedType) result);
              this.result = mType;
              return IGoal.NO_GOALS;
            }
            return subGoals.toArray(new IGoal[subGoals.size()]);
          } catch (ModelException e) {
            if (DLTKCore.DEBUG) {
              e.printStackTrace();
            }
          }
        }
        MultiTypeType type = new MultiTypeType();
        type.addType((IEvaluatedType) result);
        this.result = type;
        return IGoal.NO_GOALS;
      }
      this.result = (IEvaluatedType) result;
    }
    return IGoal.NO_GOALS;
  }

  /**
   * Check if IType is a typed array in the methodContext:
   *
   * <pre>
   *   /*
   *    *  @param SomeClass[] $elements
   *    *\/
   *    public function foo(array $elements);
   * </pre>
   *
   *
   * @param methodContext
   * @param type
   * @return boolean
   */
  private boolean isArrayType(MethodContext methodContext, IType type) {

    PHPMethodDeclaration methodDeclaration = (PHPMethodDeclaration) methodContext
        .getMethodNode();

    PHPDocBlock[] docBlocks = new PHPDocBlock[0];

    try {
      IModelElement element = methodContext.getSourceModule()
          .getElementAt(methodDeclaration.getNameStart());
      if (element instanceof IMethod) {
        IMethod method = (IMethod) element;
        if (method.getDeclaringType() != null) {
          docBlocks = PHPModelUtils
              .getTypeHierarchyMethodDoc(
                  method.getDeclaringType(),
                  methodContext.getCache() != null ? methodContext
                      .getCache().getSuperTypeHierarchy(
                          method.getDeclaringType(),
                          null) : null, method
                      .getElementName(), true, null);
        } else {
          docBlocks = new PHPDocBlock[] { methodDeclaration
              .getPHPDoc() };
        }
      } else {
        docBlocks = new PHPDocBlock[] { methodDeclaration.getPHPDoc() };
      }

    } catch (CoreException e) {
      Logger.logException(e);
    }

    if (docBlocks.length > 0) {
      for (int i = 0; i < docBlocks.length; i++) {
        if (docBlocks[i] == null) {
          continue;
        }
        PHPDocTag[] tags = docBlocks[i].getTags();
        for (int j = 0; j < tags.length; j++) {
          PHPDocTag tag = tags[j];
          if (tag.getTagKind() == PHPDocTag.PARAM) {
            SimpleReference[] refs = tag.getReferences();
            if (refs != null
                && refs.length > 1
                && refs[1]
                    .getName()
                    .equals(type.getElementName()
                        + PHPDocClassVariableEvaluator.BRACKETS)) {
              return true;
            }
          }
        }
      }
    }

    return false;
  }

  private boolean isImplementedIterator(IType[] superClasses) {
    if (superClasses == null)
      return false;
    for (IType superClass : superClasses) {
      if (superClass.getFullyQualifiedName().equalsIgnoreCase("Iterator")) { //$NON-NLS-1$
        return true;
      }
    }
    return false;
  }

}
TOP

Related Classes of org.eclipse.php.internal.core.typeinference.evaluators.IteratorTypeGoalEvaluator

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.