Package org.eclipse.php.internal.ui.editor.hyperlink

Source Code of org.eclipse.php.internal.ui.editor.hyperlink.IncludeHyperlinkVisitor

/*******************************************************************************
* Copyright (c) 2014 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.ui.editor.hyperlink;

import org.eclipse.core.runtime.Path;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.ASTVisitor;
import org.eclipse.dltk.ast.expressions.CallArgumentsList;
import org.eclipse.dltk.ast.expressions.Expression;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.jface.text.Region;
import org.eclipse.php.internal.core.compiler.ast.nodes.Include;
import org.eclipse.php.internal.core.compiler.ast.nodes.InfixExpression;
import org.eclipse.php.internal.core.compiler.ast.nodes.PHPCallExpression;
import org.eclipse.php.internal.core.compiler.ast.nodes.Scalar;
import org.eclipse.php.internal.core.compiler.ast.parser.ASTUtils;

public class IncludeHyperlinkVisitor extends ASTVisitor {

  private final static String DIRNAME_METHOD = "dirname"; //$NON-NLS-1$
  private final static String DIR_CONST = "__DIR__"; //$NON-NLS-1$
  private final static String FILE_CONST = "__FILE__"; //$NON-NLS-1$

  private boolean found = false;
  private int offset;
  private ISourceModule sourceModule;
  private StringBuilder filePath;
  private Region selectRegion;

  public IncludeHyperlinkVisitor(int offset, ISourceModule sourceModule) {
    this.offset = offset;
    this.sourceModule = sourceModule;
    this.filePath = new StringBuilder();
  }

  public boolean visit(Expression expr) throws ModelException {
    if (expr.sourceStart() < offset && expr.sourceEnd() > offset) {
      if (expr instanceof Include) {
        Expression fileExpr = ((Include) expr).getExpr();
        if (fileExpr instanceof InfixExpression) {
          processInfixExpression((InfixExpression) fileExpr);
        } else if (fileExpr instanceof Scalar) {
          processScalar((Scalar) fileExpr);
        }
        selectRegion = new Region(fileExpr.sourceStart(),
            fileExpr.sourceEnd() - fileExpr.sourceStart());
        found = true;
        return false;
      }
    }
    return !found;
  }

  private void processInfixExpression(InfixExpression infixExpression) {
    if (!infixExpression.getOperator().equals(".")) { //$NON-NLS-1$
      return;
    }
    for (ASTNode child : infixExpression.getChilds()) {
      if (child instanceof InfixExpression) {
        processInfixExpression((InfixExpression) child);
      } else if (child instanceof Scalar) {
        processScalar((Scalar) child);
      } else if (child instanceof PHPCallExpression) {
        String tmpPath = resolvePHPCallExpression((PHPCallExpression) child);
        if (tmpPath != null) {
          filePath = filePath.append(tmpPath);
        }
      }
    }
  }

  private void processScalar(Scalar scalar) {
    String resolvedValue = resolveScalarValue(scalar);
    if (resolvedValue == null) {
      return;
    }
    filePath = filePath.append(resolvedValue);
  }

  /**
   * Resolves call expression. Actually only expressions with 'dirname' method
   * and only first argument from call list is resolved.
   *
   * @param callExpression
   * @return path resolved from expression
   */
  private String resolvePHPCallExpression(PHPCallExpression callExpression) {
    if (callExpression.getCallName().getName().equals(DIRNAME_METHOD)) {
      CallArgumentsList argsList = callExpression.getArgs();
      for (ASTNode astNode : argsList.getChilds()) {
        if (astNode instanceof Scalar) {
          return resolveDirname(resolveScalarValue((Scalar) astNode));
        } else if (astNode instanceof PHPCallExpression) {
          return resolveDirname(resolvePHPCallExpression((PHPCallExpression) astNode));
        }
      }
    }
    return null;
  }

  private String resolveScalarValue(Scalar scalar) {
    if (scalar.getValue() == DIR_CONST) {
      return sourceModule.getResource().getLocation()
          .removeLastSegments(1).toOSString();
    } else if (scalar.getValue() == FILE_CONST) {
      return sourceModule.getResource().getLocation().toOSString();
    } else {
      String value = scalar.getValue();
      return ASTUtils.stripQuotes(value).trim();
    }
  }

  private String resolveDirname(String path) {
    if (path == null) {
      return null;
    }
    return new Path(path).removeLastSegments(1).toOSString();
  }

  public boolean visitGeneral(ASTNode n) {
    return !found;
  }

  public String getFile() {
    return filePath.toString();
  }

  public Region getSelectRegion() {
    return selectRegion;
  }

};
TOP

Related Classes of org.eclipse.php.internal.ui.editor.hyperlink.IncludeHyperlinkVisitor

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.