Package org.eclipse.php.formatter.core

Source Code of org.eclipse.php.formatter.core.PHPCodeFormatter

/*******************************************************************************
* Copyright (c) 2013 Zend Techologies Ltd.
* 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:
*     Zend Technologies Ltd. - initial API and implementation
*******************************************************************************/
package org.eclipse.php.formatter.core;

import java.util.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.formatter.IContentFormatter;
import org.eclipse.jface.text.formatter.IFormattingStrategy;
import org.eclipse.php.internal.core.PHPVersion;
import org.eclipse.php.internal.core.documentModel.DOMModelForPHP;
import org.eclipse.php.internal.core.format.ICodeFormattingProcessor;
import org.eclipse.php.internal.core.format.IFormatterProcessorFactory;
import org.eclipse.php.internal.core.project.ProjectOptions;
import org.eclipse.php.internal.ui.preferences.PreferenceConstants;
import org.eclipse.ui.texteditor.MarkerUtilities;
import org.eclipse.wst.html.core.internal.format.HTMLFormatProcessorImpl;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager;

/**
*
* @author moshe, 2007
*/
public class PHPCodeFormatter implements IContentFormatter,
    IFormatterProcessorFactory {

  private CodeFormatterPreferences fCodeFormatterPreferences = CodeFormatterPreferences
      .getDefaultPreferences();
  private static final Map<String, Object> defaultPrefrencesValues = CodeFormatterPreferences
      .getDefaultPreferences().getMap();

  public PHPCodeFormatter() {
  }

  private CodeFormatterPreferences getPreferences(IProject project)
      throws Exception {

    IEclipsePreferences node = null;
    if (project != null) {
      ProjectScope scope = (ProjectScope) new ProjectScope(project);
      node = scope.getNode(FormatterCorePlugin.PLUGIN_ID);
    }

    Map<String, Object> p = new HashMap<String, Object>(
        defaultPrefrencesValues);
    if (node != null
        && node.keys().length > 0
        && node.get(PreferenceConstants.FORMATTER_PROFILE, null) != null) {
      Set<String> propetiesNames = p.keySet();
      for (Iterator<String> iter = propetiesNames.iterator(); iter
          .hasNext();) {
        String property = (String) iter.next();
        String value = node.get(property, null);
        if (value != null) {
          p.put(property, value);
        }
      }
    } else {
      Preferences preferences = FormatterCorePlugin.getDefault()
          .getPluginPreferences();
      String[] propetiesNames = preferences.propertyNames();
      for (int i = 0; i < propetiesNames.length; i++) {
        String property = propetiesNames[i];
        String value = preferences.getString(property);
        if (value != null) {
          p.put(property, value);
        }
      }
    }

    fCodeFormatterPreferences.setPreferencesValues(p);

    return fCodeFormatterPreferences;
  }

  public void format(IDocument document, IRegion region) {
    IStructuredTextUndoManager undoManager = null;
    IStructuredModel structuredModel = null;
    try {
      if (document instanceof IStructuredDocument) {
        IStructuredDocument structuredDocument = (IStructuredDocument) document;
        structuredModel = StructuredModelManager.getModelManager()
            .getExistingModelForRead(document);
        DOMModelForPHP doModelForPHP = (DOMModelForPHP) structuredModel;

        IProject project = this.project;
        if (doModelForPHP != null) {
          project = getProject(doModelForPHP);
        }
        if (project == null) {
          Logger.logException(new IllegalStateException(
              "Cann't resolve file name")); //$NON-NLS-1$
          return;
        }

        undoManager = structuredDocument.getUndoManager();
        undoManager.beginRecording(this, "php format document", //$NON-NLS-1$
            "format PHP document", 0, document.getLength()); //$NON-NLS-1$

        // html format
        HTMLFormatProcessorImpl htmlFormatter = new HtmlFormatterForPhpCode();

        try {
          htmlFormatter.formatDocument(document);
        } catch (Exception e) {
          // TODO: handle exception
        }
        // php format
        PHPVersion version = ProjectOptions.getPhpVersion(project);
        boolean useShortTags = ProjectOptions.useShortTags(project);
        ICodeFormattingProcessor codeFormatterVisitor = getCodeFormattingProcessor(
            project, document, version, useShortTags, region);
        if (codeFormatterVisitor instanceof CodeFormatterVisitor) {
          List<ReplaceEdit> changes = ((CodeFormatterVisitor) codeFormatterVisitor)
              .getChanges();
          if (changes.size() > 0) {
            replaceAll(document, changes, doModelForPHP);
          }
        }

      } else {
        // TODO: how to handle other document types?
      }

    } catch (Exception e) {
      Logger.logException(e);
    } finally {
      if (undoManager != null) {
        undoManager.endRecording(this);
      }
      if (structuredModel != null) {
        structuredModel.releaseFromRead();
      }
    }
  }

  /**
   * @param doModelForPHP
   * @return project from document
   */
  private final static IProject getProject(DOMModelForPHP doModelForPHP) {
    final String id = doModelForPHP.getId();
    if (id != null) {
      final IFile file = getFile(id);
      if (file != null) {
        return file.getProject();
      }
    }
    return null;
  }

  /**
   * @param id
   * @return the file from document
   */
  private static IFile getFile(final String id) {
    return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(id));
  }

  /*
   * (non-Javadoc)
   *
   * @seeorg.eclipse.php.internal.core.format.IFormatterProcessorFactory#
   * getCodeFormattingProcessor(org.eclipse.jface.text.IDocument,
   * java.lang.Object, java.lang.String, org.eclipse.jface.text.IRegion)
   */
  public ICodeFormattingProcessor getCodeFormattingProcessor(
      IDocument document, PHPVersion phpVersion, boolean useShortTags,
      IRegion region) throws Exception {
    IProject project = getProject(document);
    return getCodeFormattingProcessor(project, document, phpVersion,
        useShortTags, region);
  }

  private ICodeFormattingProcessor getCodeFormattingProcessor(
      IProject project, IDocument document, PHPVersion phpVersion,
      boolean useShortTags, IRegion region) throws Exception {
    CodeFormatterPreferences fCodeFormatterPreferences = getPreferences(project);
    int oldCommentLength = fCodeFormatterPreferences.comment_line_length;
    boolean forceSplit = fCodeFormatterPreferences.line_wrap_expressions_in_array_init_force_split;
    boolean insertSpaceAfterComma = fCodeFormatterPreferences.insert_space_after_list_comma_in_array;
    boolean insertNewLineBeforeCloseArray = fCodeFormatterPreferences.new_line_before_close_array_parenthesis_array;
    int lineWrapPolicy = fCodeFormatterPreferences.line_wrap_expressions_in_array_init_line_wrap_policy;
    if (isPasting) {
      fCodeFormatterPreferences.comment_line_length = 400;
      fCodeFormatterPreferences.line_wrap_expressions_in_array_init_force_split = true;
      fCodeFormatterPreferences.line_wrap_expressions_in_array_init_line_wrap_policy = CodeFormatterVisitor.WRAP_ALL_ELEMENTS;
      fCodeFormatterPreferences.insert_space_after_list_comma_in_array = false;
      fCodeFormatterPreferences.new_line_before_close_array_parenthesis_array = true;
    }
    ICodeFormattingProcessor codeFormattingProcessor = new CodeFormatterVisitor(
        document, fCodeFormatterPreferences, getLineSeparator(project),
        phpVersion, useShortTags, region);

    if (isPasting) {
      fCodeFormatterPreferences.comment_line_length = oldCommentLength;
      fCodeFormatterPreferences.line_wrap_expressions_in_array_init_force_split = forceSplit;
      fCodeFormatterPreferences.line_wrap_expressions_in_array_init_line_wrap_policy = lineWrapPolicy;
      fCodeFormatterPreferences.insert_space_after_list_comma_in_array = insertSpaceAfterComma;
      fCodeFormatterPreferences.new_line_before_close_array_parenthesis_array = insertNewLineBeforeCloseArray;
    }
    return codeFormattingProcessor;
  }

  private String getLineSeparator(IProject project) {
    String lineSeparator = null;
    if (project != null) {
      lineSeparator = Platform.getPreferencesService().getString(
          Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null,
          new IScopeContext[] { new ProjectScope(project) });
    }
    if (lineSeparator == null) {
      lineSeparator = Platform.getPreferencesService().getString(
          Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null,
          new IScopeContext[] { InstanceScope.INSTANCE });
    }
    if (lineSeparator == null) {
      lineSeparator = System.getProperty(Platform.PREF_LINE_SEPARATOR);
    }
    return lineSeparator;
  }

  private IProject getProject(IDocument document) {
    IProject project = null;
    IStructuredModel structuredModel = null;
    if (document instanceof IStructuredDocument) {
      try {
        structuredModel = StructuredModelManager.getModelManager()
            .getExistingModelForRead(document);
        DOMModelForPHP doModelForPHP = (DOMModelForPHP) structuredModel;
        project = getProject(doModelForPHP);
      } finally {
        if (structuredModel != null) {
          structuredModel.releaseFromRead();
        }
      }
    }
    return project;
  }

  private void replaceAll(IDocument document, List<ReplaceEdit> changes,
      DOMModelForPHP domModelForPHP) throws BadLocationException {
    // Collect the markers before the content of the document is replaced.
    IFile file = null;
    IMarker[] allMarkers = null;
    if (domModelForPHP != null) {
      file = getFile(domModelForPHP.getId());
      try {
        if (file != null) {
          // collect and then delete
          allMarkers = file.findMarkers(null, true,
              IResource.DEPTH_INFINITE);
        } else {
          return; // no need to save breakpoints when no file was
          // detected
        }
      } catch (CoreException e) {
      }
    }

    // Replace the content of the document
    StringBuffer buffer = new StringBuffer(document.get());
    for (int i = changes.size() - 1; i >= 0; i--) {
      ReplaceEdit replace = (ReplaceEdit) changes.get(i);
      buffer.replace(replace.offset, replace.getEnd(), replace.content);
    }
    document.set(buffer.toString());

    try {
      if (file != null) {
        reinsertMarkers(allMarkers, file);
      }
    } catch (CoreException e) {
    }
  }

  // Return the markers
  // TODO - This is buggy since the lines might be different now.
  private void reinsertMarkers(IMarker[] allMarkers, IFile file)
      throws CoreException {
    final IBreakpointManager breakpointManager = DebugPlugin.getDefault()
        .getBreakpointManager();
    if (allMarkers != null) {
      for (IMarker marker : allMarkers) {
        String markerType = MarkerUtilities.getMarkerType(marker);
        if (markerType != null) {
          IBreakpoint breakpoint = breakpointManager
              .getBreakpoint(marker);
          if (breakpoint != null) {
            IMarker createdMarker = file.createMarker(markerType);
            createdMarker.setAttributes(breakpoint.getMarker()
                .getAttributes());
            breakpointManager.removeBreakpoint(breakpoint, true);
            breakpoint.setMarker(createdMarker);
            breakpointManager.addBreakpoint(breakpoint);
          } else {
            MarkerUtilities.createMarker(file,
                marker.getAttributes(), markerType);
          }
        }
        marker.delete();
      }
    }
  }

  public IFormattingStrategy getFormattingStrategy(String contentType) {
    return null;
  }

  private IProject project;
  private boolean isPasting = false;

  public void setDefaultProject(IProject project) {
    this.project = project;
  }

  public void setIsPasting(boolean isPasting) {
    this.isPasting = isPasting;
  }

  public void format(IDocument document, IRegion region, PHPVersion version) {
    // TODO Auto-generated method stub

    IStructuredTextUndoManager undoManager = null;
    IStructuredModel structuredModel = null;
    try {
      if (document instanceof IStructuredDocument) {
        IStructuredDocument structuredDocument = (IStructuredDocument) document;
        structuredModel = StructuredModelManager.getModelManager()
            .getExistingModelForRead(document);
        DOMModelForPHP doModelForPHP = (DOMModelForPHP) structuredModel;

        IProject project = this.project;
        if (doModelForPHP != null) {
          project = getProject(doModelForPHP);
        }
        if (project == null) {
          Logger.logException(new IllegalStateException(
              "Cann't resolve file name")); //$NON-NLS-1$
          return;
        }

        undoManager = structuredDocument.getUndoManager();
        undoManager.beginRecording(this, "php format document", //$NON-NLS-1$
            "format PHP document", 0, document.getLength()); //$NON-NLS-1$

        // html format
        HTMLFormatProcessorImpl htmlFormatter = new HtmlFormatterForPhpCode();

        try {
          htmlFormatter.formatDocument(document);
        } catch (Exception e) {
          // TODO: handle exception
        }
        // php format
        // PHPVersion version = ProjectOptions.getPhpVersion(project);
        boolean useShortTags = ProjectOptions.useShortTags(project);
        ICodeFormattingProcessor codeFormatterVisitor = getCodeFormattingProcessor(
            project, document, version, useShortTags, region);
        if (codeFormatterVisitor instanceof CodeFormatterVisitor) {
          List<ReplaceEdit> changes = ((CodeFormatterVisitor) codeFormatterVisitor)
              .getChanges();
          if (changes.size() > 0) {
            replaceAll(document, changes, doModelForPHP);
          }
        }

      } else {
        // TODO: how to handle other document types?
      }

    } catch (Exception e) {
      Logger.logException(e);
    } finally {
      if (undoManager != null) {
        undoManager.endRecording(this);
      }
      if (structuredModel != null) {
        structuredModel.releaseFromRead();
      }
    }

  }

}
TOP

Related Classes of org.eclipse.php.formatter.core.PHPCodeFormatter

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.