Package org.eclipse.php.internal.core.validation

Source Code of org.eclipse.php.internal.core.validation.PHPTodoTaskValidator

/*******************************************************************************
* 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.validation;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IRegion;
import org.eclipse.php.internal.core.CoreMessages;
import org.eclipse.php.internal.core.Logger;
import org.eclipse.php.internal.core.PHPCoreConstants;
import org.eclipse.php.internal.core.PHPToolkitUtil;
import org.eclipse.php.internal.core.documentModel.parser.regions.PHPRegionTypes;
import org.eclipse.php.internal.core.documentModel.parser.regions.PhpScriptRegion;
import org.eclipse.php.internal.core.preferences.TaskTagsProvider;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.tasks.TaskTag;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.validation.AbstractValidator;
import org.eclipse.wst.validation.ValidationResult;
import org.eclipse.wst.validation.ValidationState;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
import org.eclipse.wst.xml.core.internal.parser.ContextRegionContainer;

/**
* This Validator creates (and removes) the task markers that will eventually
* show up in the task view
*
* @author Eden K.,2008
*
*/
public class PHPTodoTaskValidator extends AbstractValidator {

  protected TaskTag[] taskTags = null;

  public ValidationResult validate(IResource resource, int kind,
      ValidationState state, IProgressMonitor monitor) {
    // process only PHP files
    if (resource.getType() != IResource.FILE
        || !(PHPToolkitUtil.isPhpFile((IFile) resource))) {
      return null;
    }

    ValidationResult result = new ValidationResult();
    IReporter reporter = result.getReporter(monitor);
    validateFile(reporter, (IFile) resource, kind);

    return result;
  }

  /**
   * Search for tasks in the validated file and create a marker for each task
   * found
   */
  public void validateFile(IReporter reporter, IFile file, int kind) {

    // populate the task tags from the preferences
    // in case it is empty or it is a clean/full build
    if (taskTags == null || (kind == 0)) {
      populateTaskTags(file);
    }

    // remove the markers currently existing for this resource
    // in case of project/folder, the markers are deleted recursively
    try {
      file.deleteMarkers(PHPCoreConstants.PHP_MARKER_TYPE, false,
          IResource.DEPTH_INFINITE);
    } catch (CoreException e) {
    }
    IStructuredModel model = null;
    try {
      // desperately try to get the model :) In case it doesn't exist yet,
      // create it
      try {
        model = StructuredModelManager.getModelManager()
            .getExistingModelForRead(file);
      } catch (Exception e) {
        try {
          model = StructuredModelManager.getModelManager()
              .createUnManagedStructuredModelFor(file);
        } catch (Exception e2) {
        }
      }
      if (model == null) {
        return;
      }
      // collect the tasks info and report
      IStructuredDocumentRegion[] sdRegions = model
          .getStructuredDocument().getStructuredDocumentRegions();
      for (IStructuredDocumentRegion structuredDocumentRegion : sdRegions) {

        IStructuredDocument document = structuredDocumentRegion
            .getParentDocument();

        ITextRegionList textRegions = structuredDocumentRegion
            .getRegions();
        for (int i = 0; i < textRegions.size(); i++) {
          ITextRegion textRegion = textRegions.get(i);
          int regionStart = structuredDocumentRegion
              .getStartOffset(textRegion);

          // special handling for php tags inside html
          if (textRegion instanceof ContextRegionContainer) {
            textRegion = extractPhpScriptRegion(textRegion);
            regionStart += textRegion.getStart();
          }
          // parse the actual script
          if (textRegion instanceof PhpScriptRegion) {
            PhpScriptRegion scriptRegion = (PhpScriptRegion) textRegion;
            try {

              // go over the text regions and look for the tasks
              ITextRegion[] phpTokens = scriptRegion
                  .getPhpTokens(0, textRegion.getLength());
              for (int j = 0; j < phpTokens.length; j++) {
                ITextRegion phpToken = phpTokens[j];
                if (PHPRegionTypes.PHPDOC_TODO.equals(phpToken
                    .getType())) {
                  // get the task information from the
                  // document
                  int offset = regionStart
                      + phpToken.getStart();
                  int length = phpToken.getLength();

                  String taskKeyword = document.get(offset,
                      phpToken.getLength());
                  int priority = getTaskPriority(taskKeyword);

                  // get the actual message for this task - if
                  // any
                  if (j + 1 < phpTokens.length) {
                    for (int k = j + 1; k < phpTokens.length; k++) {
                      ITextRegion phpNextToken = phpTokens[k];
                      if (PHPRegionTypes.PHPDOC_TODO
                          .equals(phpNextToken
                              .getType())) {
                        break;
                      }
                      length = length
                          + phpNextToken.getLength();
                    }
                  }

                  try {
                    reportTask(document, file, reporter,
                        offset, length, priority);
                  } catch (CoreException e) {
                    Logger.logException(
                        "Failed creating task", e); //$NON-NLS-1$
                  }
                }
              }
            } catch (BadLocationException e) {
              Logger.logException(CoreMessages
                  .getString("PHPTodoTaskAstParser_0"), e); //$NON-NLS-1$
            }
          }
        }
      }
    } catch (Exception e) {
      Logger.logException("Failed validating file for tasks " + file, e); //$NON-NLS-1$
    } finally {
      if (model != null) {
        model.releaseFromRead();
        model = null;
      }

    }

  }

  /**
   * Get the project and populate the task tags list from the preferences
   *
   * @param helper
   */
  private void populateTaskTags(IFile file) {
    TaskTagsProvider taskTagsProvider = TaskTagsProvider.getInstance();
    getTaskTags(file.getProject(), taskTagsProvider);
  }

  public void cleanup(IReporter reporter) {
  }

  /**
   * Get the task tags from the preferences
   *
   * @param project
   * @param taskTagsProvider
   */
  private void getTaskTags(IProject project, TaskTagsProvider taskTagsProvider) {
    taskTags = taskTagsProvider.getProjectTaskTags(project);
    if (taskTags == null) {
      taskTags = taskTagsProvider.getWorkspaceTaskTags();
    }
  }

  /**
   * @param delta
   *            the IFileDelta containing the file name to get
   * @return the IFile
   */
  public IFile getFile(String delta) {
    IResource res = ResourcesPlugin.getWorkspace().getRoot()
        .getFile(new Path(delta));
    return res instanceof IFile ? (IFile) res : null;
  }

  /**
   * Get the task priority according to the preferences
   *
   * @return
   */
  private int getTaskPriority(String taskStr) {

    String taskTagLowerCase = taskStr.toLowerCase();
    for (int i = 0; i < taskTags.length; i++) {
      TaskTag taskTag = taskTags[i];
      if (taskTag.getTag().toLowerCase().equals(taskTagLowerCase)) {
        return taskTag.getPriority();
      }
    }

    return TaskTag.PRIORITY_NORMAL;
  }

  /**
   * Reports the task
   *
   * @param document
   * @param taskReporter
   * @param offset
   * @param length
   * @param priority
   * @throws BadLocationException
   * @throws CoreException
   */
  private void reportTask(IStructuredDocument document, IFile file,
      IReporter taskReporter, int offset, int length, int priority)
      throws BadLocationException, CoreException {
    int lineNumber = document.getLineOfOffset(offset);

    String taskStr = getTaskStr(document, lineNumber, offset, length);
    // the end of the string to be highlighted
    int charEnd = offset + taskStr.length();

    // report the task
    createMarker(file, taskStr, lineNumber, priority, offset, charEnd);

  }

  /**
   * Creates a PHP task marker based on the given information
   *
   * @param file
   * @param taskStr
   * @param lineNumber
   * @param priority
   * @param offset
   * @param charEnd
   * @throws CoreException
   */
  private void createMarker(IFile file, String taskStr, int lineNumber,
      int priority, int offset, int charEnd) throws CoreException {
    IMarker marker = file.createMarker(PHPCoreConstants.PHP_MARKER_TYPE);

    marker.setAttribute(IMarker.TASK, true);

    marker.setAttribute(IMarker.LINE_NUMBER, lineNumber + 1);
    marker.setAttribute(IMarker.CHAR_START, offset);
    marker.setAttribute(IMarker.CHAR_END, charEnd);
    marker.setAttribute(IMarker.MESSAGE, taskStr);
    marker.setAttribute(IMarker.USER_EDITABLE, false);
    marker.setAttribute(IMarker.PRIORITY, priority);
  }

  /**
   * Gets the Task message from the document
   *
   * @param document
   * @param lineNumber
   * @param offset
   * @param length
   * @return
   * @throws BadLocationException
   */
  private String getTaskStr(IStructuredDocument document, int lineNumber,
      int offset, int length) throws BadLocationException {
    // get line info to identify the end of the task
    IRegion lineInformation = document.getLineInformation(lineNumber);
    int lineStart = lineInformation.getOffset();
    int lineEnd = lineStart + lineInformation.getLength();

    // identify the actual end of the task: either end of line or end of the
    // token
    // we could have 2 tasks in the same line
    int tokenEnd = offset + length;
    int taskEnd = Math.min(tokenEnd, lineEnd);

    String taskStr = document.get(offset, taskEnd - offset);
    taskStr = taskStr.trim();

    return taskStr;

  }

  /**
   * Given a ContextRegionContainer, looks for the PHPScriptRegion in it and
   * return it. If the container does not contain a PHPScript region, just
   * return the given TextRegion
   *
   * @param textRegion
   * @return the PhpScript textRegion
   */
  private ITextRegion extractPhpScriptRegion(ITextRegion textRegion) {
    ContextRegionContainer container = (ContextRegionContainer) textRegion;
    ITextRegionList containerRegions = container.getRegions();
    for (int z = 0; z < containerRegions.size(); z++) {
      ITextRegion containerTextRegion = containerRegions.get(z);
      if (containerTextRegion instanceof PhpScriptRegion) {
        return containerTextRegion;
      }
    }
    return textRegion;
  }

}
TOP

Related Classes of org.eclipse.php.internal.core.validation.PHPTodoTaskValidator

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.