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

Source Code of org.eclipse.php.internal.core.typeinference.evaluators.phpdoc.PHPDocClassVariableEvaluator

/*******************************************************************************
* 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 org.eclipse.php.internal.core.typeinference.evaluators.phpdoc;

import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
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.goals.IGoal;
import org.eclipse.dltk.ti.types.IEvaluatedType;
import org.eclipse.php.internal.core.compiler.ast.nodes.NamespaceReference;
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.UsePart;
import org.eclipse.php.internal.core.typeinference.*;
import org.eclipse.php.internal.core.typeinference.context.TypeContext;
import org.eclipse.php.internal.core.typeinference.evaluators.AbstractPHPGoalEvaluator;
import org.eclipse.php.internal.core.typeinference.goals.phpdoc.PHPDocClassVariableGoal;

/**
* This evaluator finds class field declartion either using "var" or in method
* body using field access.
*/
public class PHPDocClassVariableEvaluator extends AbstractPHPGoalEvaluator {

  private static final String SPLASH = "\\"; //$NON-NLS-1$

  public static final String BRACKETS = "[]"; //$NON-NLS-1$

  private List<IEvaluatedType> evaluated = new LinkedList<IEvaluatedType>();

  public final static Pattern ARRAY_TYPE_PATTERN = Pattern
      .compile("array\\[.*\\]"); //$NON-NLS-1$

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

  public IGoal[] init() {
    PHPDocClassVariableGoal typedGoal = (PHPDocClassVariableGoal) goal;
    TypeContext context = (TypeContext) typedGoal.getContext();
    String variableName = typedGoal.getVariableName();
    int offset = typedGoal.getOffset();

    IModelAccessCache cache = context.getCache();
    IType[] types = PHPTypeInferenceUtils.getModelElements(
        context.getInstanceType(), context, offset, cache);
    Map<PHPDocBlock, IField> docs = new HashMap<PHPDocBlock, IField>();

    if (types != null) {
      for (IType type : types) {
        try {
          // we look in whole hiearchy
          ITypeHierarchy superHierarchy;
          if (cache != null) {
            superHierarchy = cache
                .getSuperTypeHierarchy(type, null);
          } else {
            superHierarchy = type.newSupertypeHierarchy(null);
          }
          IType[] superTypes = superHierarchy.getAllTypes();
          for (IType superType : superTypes) {
            IField[] typeField = PHPModelUtils.getTypeField(
                superType, variableName, true);
            if (typeField.length > 0) {
              PHPDocBlock docBlock = PHPModelUtils
                  .getDocBlock(typeField[0]);
              if (docBlock != null) {
                docs.put(docBlock, typeField[0]);
              }
            }
          }
        } catch (ModelException e) {
          if (DLTKCore.DEBUG) {
            e.printStackTrace();
          }
        }
      }
    }

    for (Entry<PHPDocBlock, IField> entry : docs.entrySet()) {
      PHPDocBlock doc = entry.getKey();
      IField typeField = entry.getValue();
      IType currentNamespace = PHPModelUtils
          .getCurrentNamespace(typeField);
      for (PHPDocTag tag : doc.getTags()) {
        if (tag.getTagKind() == PHPDocTag.VAR) {
          SimpleReference[] references = tag.getReferences();
          for (SimpleReference ref : references) {
            String typeName = ref.getName();
            Matcher m = ARRAY_TYPE_PATTERN.matcher(typeName);
            if (m.find()) {
              evaluated.add(getArrayType(m.group(),
                  currentNamespace, doc.sourceStart()));
            } else if (typeName.endsWith(BRACKETS)
                && typeName.length() > 2) {
              offset = 0;
              try {
                offset = typeField.getSourceRange().getOffset();
              } catch (ModelException e) {
              }
              evaluated.add(getArrayType(typeName.substring(0,
                  typeName.length() - 2), currentNamespace,
                  offset));

            } else {
              if (currentNamespace != null) {
                ModuleDeclaration moduleDeclaration = SourceParserUtil
                    .getModuleDeclaration(currentNamespace
                        .getSourceModule());
                if (typeName.indexOf(SPLASH) > 0) {
                  // check if the first part is an
                  // alias,then get the full name
                  String prefix = typeName.substring(0,
                      typeName.indexOf(SPLASH));
                  final Map<String, UsePart> result = PHPModelUtils
                      .getAliasToNSMap(prefix,
                          moduleDeclaration,
                          doc.sourceStart(),
                          currentNamespace, true);
                  if (result.containsKey(prefix)) {
                    String fullName = result.get(prefix)
                        .getNamespace()
                        .getFullyQualifiedName();
                    typeName = typeName.replace(prefix,
                        fullName);
                    if (typeName.charAt(0) != NamespaceReference.NAMESPACE_SEPARATOR) {
                      typeName = NamespaceReference.NAMESPACE_SEPARATOR
                          + typeName;
                    }
                  }
                } else if (typeName.indexOf(SPLASH) < 0) {
                  String prefix = typeName;
                  final Map<String, UsePart> result = PHPModelUtils
                      .getAliasToNSMap(prefix,
                          moduleDeclaration,
                          doc.sourceStart(),
                          currentNamespace, true);
                  if (result.containsKey(prefix)) {
                    String fullName = result.get(prefix)
                        .getNamespace()
                        .getFullyQualifiedName();
                    typeName = fullName;
                    if (typeName.charAt(0) != NamespaceReference.NAMESPACE_SEPARATOR) {
                      typeName = NamespaceReference.NAMESPACE_SEPARATOR
                          + typeName;
                    }
                  }
                }
              }

              IEvaluatedType type = getEvaluatedType(typeName,
                  currentNamespace);
              if (type != null) {
                evaluated.add(type);
              }
              // IEvaluatedType type = PHPClassType
              // .fromSimpleReference(ref);
              // evaluated.add(type);
            }

          }
        }
      }
    }

    return IGoal.NO_GOALS;
  }

  public Object produceResult() {
    return PHPTypeInferenceUtils.combineTypes(evaluated);
  }

  public IGoal[] subGoalDone(IGoal subgoal, Object result, GoalState state) {
    if (state != GoalState.RECURSIVE && result != null) {
      evaluated.add((IEvaluatedType) result);
    }
    return IGoal.NO_GOALS;
  }

  public static MultiTypeType getArrayType(String type,
      IType currentNamespace, int offset) {
    int beginIndex = type.indexOf("[") + 1; //$NON-NLS-1$
    int endIndex = type.lastIndexOf("]"); //$NON-NLS-1$
    if (endIndex != -1) {
      type = type.substring(beginIndex, endIndex);
    }
    MultiTypeType arrayType = new MultiTypeType();
    Matcher m = ARRAY_TYPE_PATTERN.matcher(type);
    if (m.find()) {
      arrayType
          .addType(getArrayType(m.group(), currentNamespace, offset));
      type = m.replaceAll(""); //$NON-NLS-1$
    }
    String[] typeNames = type.split(","); //$NON-NLS-1$
    for (String name : typeNames) {
      if (!"".equals(name)) { //$NON-NLS-1$

        if (name.indexOf(NamespaceReference.NAMESPACE_SEPARATOR) > 0
            && currentNamespace != null) {
          // check if the first part is an
          // alias,then get the full name
          ModuleDeclaration moduleDeclaration = SourceParserUtil
              .getModuleDeclaration(currentNamespace
                  .getSourceModule());
          String prefix = name.substring(0, name
              .indexOf(NamespaceReference.NAMESPACE_SEPARATOR));
          final Map<String, UsePart> result = PHPModelUtils
              .getAliasToNSMap(prefix, moduleDeclaration, offset,
                  currentNamespace, true);
          if (result.containsKey(prefix)) {
            String fullName = result.get(prefix).getNamespace()
                .getFullyQualifiedName();
            name = name.replace(prefix, fullName);
            if (name.charAt(0) != NamespaceReference.NAMESPACE_SEPARATOR) {
              name = NamespaceReference.NAMESPACE_SEPARATOR
                  + name;
            }
          }
        }
        arrayType.addType(getEvaluatedType(name, currentNamespace));
      }
    }
    return arrayType;
  }

  public static IEvaluatedType getEvaluatedType(String typeName,
      IType currentNamespace) {
    IEvaluatedType type = PHPSimpleTypes.fromString(typeName);
    if (type == null) {
      if (typeName.indexOf(NamespaceReference.NAMESPACE_SEPARATOR) > 0
          && currentNamespace != null) {
        typeName = NamespaceReference.NAMESPACE_SEPARATOR
            + currentNamespace.getElementName()
            + NamespaceReference.NAMESPACE_SEPARATOR + typeName;
      }
      if (typeName.indexOf(NamespaceReference.NAMESPACE_SEPARATOR) != -1
          || currentNamespace == null) {
        type = new PHPClassType(typeName);
      } else {
        type = new PHPClassType(currentNamespace.getElementName(),
            typeName);
      }
    }
    return type;
  }

}
TOP

Related Classes of org.eclipse.php.internal.core.typeinference.evaluators.phpdoc.PHPDocClassVariableEvaluator

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.