Package org.eclim.plugin.cdt.project

Source Code of org.eclim.plugin.cdt.project.CProjectManager

/**
* Copyright (C) 2005 - 2012  Eric Van Dewoestine
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.eclim.plugin.cdt.project;

import java.io.FileInputStream;

import java.util.Arrays;
import java.util.List;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclim.Services;

import org.eclim.command.CommandLine;
import org.eclim.command.Error;

import org.eclim.eclipse.EclimPlugin;

import org.eclim.plugin.cdt.PluginResources;

import org.eclim.plugin.cdt.util.CUtils;

import org.eclim.plugin.core.project.ProjectManager;

import org.eclim.plugin.core.util.XmlUtils;

import org.eclim.util.IOUtils;

import org.eclim.util.file.FileOffsets;

import org.eclipse.cdt.core.CCorePlugin;

import org.eclipse.cdt.core.index.IIndexManager;

import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICModelStatus;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.IPathEntry;

import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;

import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;

import org.eclipse.cdt.core.settings.model.util.PathEntryTranslator;

import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyManager;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyValue;

import org.eclipse.cdt.managedbuilder.core.BuildListComparator;
import org.eclipse.cdt.managedbuilder.core.IBuilder;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;

import org.eclipse.cdt.managedbuilder.internal.core.Configuration;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedProject;
import org.eclipse.cdt.managedbuilder.internal.core.ToolChain;

import org.eclipse.cdt.managedbuilder.internal.dataprovider.ConfigurationDataProvider;

import org.eclipse.cdt.managedbuilder.ui.wizards.CfgHolder;
import org.eclipse.cdt.managedbuilder.ui.wizards.MBSWizardHandler;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;

import org.eclipse.jface.wizard.IWizard;

import org.eclipse.swt.widgets.Composite;

/**
* Manager for c/c++ projects.
*
* @author Eric Van Dewoestine
*/
public class CProjectManager
  implements ProjectManager
{
  private static final String CPROJECT_XSD =
    "/resources/schema/eclipse/cproject.xsd";

  private static final Pattern ENTRY_PATTERN =
    Pattern.compile(".*?:\\s+/.*?/(.*)\\s+for .*");

  private static final Pattern INCLUDE_PATTERN =
    Pattern.compile(".*?\\((.*?)\\).*");

  @Override
  public void create(final IProject project, CommandLine commandLine)
    throws Exception
  {
    // TODO: - support other project types:
    //         executable, shared library, static library
    //       - support specifying the toolchain to use.

    final IBuildPropertyManager buildManager =
      ManagedBuildManager.getBuildPropertyManager();
    final IBuildPropertyValue[] vs = buildManager
      .getPropertyType(MBSWizardHandler.ARTIFACT).getSupportedValues();
    Arrays.sort(vs, BuildListComparator.getInstance());

    MBSWizardHandler handler = null;

    toolchainLoop:
    for (IBuildPropertyValue value : vs){
      final IToolChain[] toolChains = ManagedBuildManager
        .getExtensionsToolChains(MBSWizardHandler.ARTIFACT, value.getId(), false);
      if (toolChains != null && toolChains.length > 0){
        for (IToolChain tc : toolChains){
          if (!tc.isAbstract() &&
              !tc.isSystemObject() &&
              tc.isSupported() &&
              ManagedBuildManager.isPlatformOk(tc))
          {
            handler = new LocalMBSWizardHandler(
                value, EclimPlugin.getShell(), null, tc);

            // stop once we've found a toolchain w/ a config
            CfgHolder[] cfgs = handler.getCfgItems(false);
            if (cfgs != null &&
                cfgs.length > 0 &&
                cfgs[0].getConfiguration() != null)
            {
              break toolchainLoop;
            }
          }
        }

        // handle case where no toolchain w/ a config was found, like on
        // windows when eclipse can't find cygwin or mingw.
        IToolChain ntc = ManagedBuildManager
          .getExtensionToolChain(ConfigurationDataProvider.PREF_TC_ID);
        handler = new LocalSTDWizardHandler(
            value, EclimPlugin.getShell(), null, ntc);
      }
    }

    try{
      handler.createProject(project, true, true, new NullProgressMonitor());
      ICProject cproject = CUtils.getCProject(project);
      CCorePlugin.getIndexManager().reindex(cproject);
    }catch(Exception e){
      throw new RuntimeException(e);
    }
  }

  @Override
  public List<Error> update(IProject project, CommandLine commandLine)
    throws Exception
  {
    PluginResources resources = (PluginResources)
      Services.getPluginResources(PluginResources.NAME);
    List<Error> errors = XmlUtils.validateXml(
        project.getName(),
        ".cproject",
        resources.getResource(CPROJECT_XSD).toString());
    if(errors.size() > 0){
      return errors;
    }

    // FIXME: force load of file from disk
    ICProjectDescriptionManager manager =
      CoreModel.getDefault().getProjectDescriptionManager();
    //manager.updateProjectDescriptions(new IProject[]{project}, null);

    ICProjectDescription desc = manager.getProjectDescription(project, false);

    ICConfigurationDescription config = desc.getDefaultSettingConfiguration();
    PathEntryTranslator.PathEntryCollector cr =
      PathEntryTranslator.collectEntries(project, config);

    IPathEntry[] entries = cr.getEntries(
        PathEntryTranslator.INCLUDE_USER, config);
    ICProject cproject = CoreModel.getDefault().create(project);
    String dotcproject = project.getFile(".cproject").getRawLocation().toOSString();
    FileOffsets offsets = FileOffsets.compile(dotcproject);
    String cprojectValue = IOUtils.toString(new FileInputStream(dotcproject));
    for (IPathEntry entry : entries){
      ICModelStatus status =
        CoreModel.validatePathEntry(cproject, entry, true, true);
      if(!status.isOK()){
        errors.add(createErrorFromStatus(
              offsets, dotcproject, cprojectValue, entry, status));
      }
    }
    return errors;
  }

  @Override
  public void delete(IProject project, CommandLine commandLine)
    throws Exception
  {
  }

  @Override
  public void refresh(IProject project, CommandLine commandLine)
    throws Exception
  {
    ICProject cproject = CUtils.getCProject(project);
    CCorePlugin.getIndexManager().reindex(cproject);
    CCorePlugin.getIndexManager()
      .joinIndexer(IIndexManager.FOREVER, new NullProgressMonitor());
  }

  @Override
  public void refresh(IProject project, IFile file)
    throws Exception
  {
  }

  /**
   * Creates an Error from the supplied IJavaModelStatus.
   *
   * @param offsets File offsets for the classpath file.
   * @param filename The filename of the error.
   * @param contents The contents of the file as a String.
   * @param status The IJavaModelStatus.
   * @return The Error.
   */
  private Error createErrorFromStatus(
      FileOffsets offsets,
      String filename,
      String contents,
      IPathEntry entry,
      ICModelStatus status)
    throws Exception
  {
    int line = 0;
    int col = 0;

    // get the pattern to search for from the status message.
    Matcher matcher = null;
    String pattern = null;
    switch(entry.getEntryKind()){
      case IPathEntry.CDT_OUTPUT:
      case IPathEntry.CDT_SOURCE:
        matcher = ENTRY_PATTERN.matcher(status.getString());
        pattern = "name=\"" + matcher.replaceFirst("$1") + "\"";
        break;
      case IPathEntry.CDT_INCLUDE:
      case IPathEntry.CDT_INCLUDE_FILE:
        matcher = INCLUDE_PATTERN.matcher(status.getString());
        pattern = "value=\"" + matcher.replaceFirst("$1") + "\"";
        break;
    }

    if (matcher != null){
      // find the pattern in the classpath file.
      matcher = Pattern.compile("\\Q" + pattern + "\\E").matcher(contents);
      if(matcher.find()){
        int[] position = offsets.offsetToLineColumn(matcher.start());
        line = position[0];
        col = position[1];
      }
    }

    return new Error(status.getMessage(), filename, line, col, false);
  }

  private class LocalMBSWizardHandler
    extends MBSWizardHandler
  {
    private IToolChain toolchain;

    public LocalMBSWizardHandler(
        IBuildPropertyValue val, Composite p, IWizard w, IToolChain tc)
    {
      super(val, p, w);
      this.toolchain = tc;
    }

    public IToolChain[] getSelectedToolChains()
    {
      return new IToolChain[]{toolchain};
    }

    protected void doCustom(IProject project)
    {
      // no-op
    }

    public CfgHolder[] getCfgItems(boolean defaults)
    {
      CfgHolder[] cfgs = super.getCfgItems(defaults);
      if (cfgs == null || cfgs.length == 0){
        IToolChain tc = ManagedBuildManager
          .getExtensionToolChain(ConfigurationDataProvider.PREF_TC_ID);
        cfgs = new CfgHolder[1];
        cfgs[0] = new CfgHolder(tc, null);
      }
      return cfgs;
    }

    /*public CfgHolder[] getCfgItems(boolean defaults)
    {
      CfgHolder[] cfg = super.getCfgItems(true);

      if (cfg == null || cfg.length == 0){
        IConfiguration config = ManagedBuildManager
          .getExtensionConfiguration(
              "org.eclipse.cdt.build.core.prefbase.cfg");
        //.getExtensionConfiguration(ConfigurationDataProvider.PREF_CFG_ID);

        IToolChain noTc = ManagedBuildManager
          .getExtensionToolChain(ConfigurationDataProvider.PREF_TC_ID);

        cfg = new CfgHolder[1];
        cfg[0] = new CfgHolder(noTc, config);
        logger.warn("No suitable toolchain config found, " +
            "using 'No Toolchain' config.");
      }
      return cfg;
    }*/
  }

  private class LocalSTDWizardHandler
    extends LocalMBSWizardHandler
  {
    public LocalSTDWizardHandler(
        IBuildPropertyValue val, Composite p, IWizard w, IToolChain tc)
    {
      super(val, p, w, tc);
    }

    /**** Copied from STDWizardHandler ****/
    public void createProject(
        IProject project,
        boolean defaults,
        boolean onFinish,
        IProgressMonitor monitor)
      throws CoreException
    {
      try {
        monitor.beginTask("", 100); //$NON-NLS-1$

        setProjectDescription(project, defaults, onFinish, monitor);

        doTemplatesPostProcess(project);
        doCustom(project);
        monitor.worked(30);
      } finally {
        monitor.done();
      }
    }

    /**** Copied from STDWizardHandler ****/
    private void setProjectDescription(
        IProject project,
        boolean defaults,
        boolean onFinish,
        IProgressMonitor monitor)
      throws CoreException
    {
        ICProjectDescriptionManager mngr =
          CoreModel.getDefault().getProjectDescriptionManager();
        ICProjectDescription des =
          mngr.createProjectDescription(project, false, !onFinish);
        ManagedBuildInfo info = ManagedBuildManager.createBuildInfo(project);
        ManagedProject mProj = new ManagedProject(des);
        info.setManagedProject(mProj);
        monitor.worked(20);
        cfgs = CfgHolder.unique(getCfgItems(false));
        cfgs = CfgHolder.reorder(cfgs);
        int work = 50 / cfgs.length;
        for (int i = 0; i < cfgs.length; i++) {
          String s = (cfgs[i].getToolChain() == null) ?
            "0" : ((ToolChain)(cfgs[i].getToolChain())).getId()//$NON-NLS-1$
          Configuration cfg = new Configuration(
              mProj,
              (ToolChain)cfgs[i].getToolChain(),
              ManagedBuildManager.calculateChildId(s, null),
              cfgs[i].getName());
          cfgs[i].setConfiguration(cfg);
          IBuilder bld = cfg.getEditableBuilder();
          if (bld != null) {
            if(bld.isInternalBuilder()){
              IConfiguration prefCfg =
                ManagedBuildManager.getPreferenceConfiguration(false);
              IBuilder prefBuilder = prefCfg.getBuilder();
              cfg.changeBuilder(
                  prefBuilder,
                  ManagedBuildManager.calculateChildId(cfg.getId(), null),
                  prefBuilder.getName());
              bld = cfg.getEditableBuilder();
              bld.setBuildPath(null);
            }
            bld.setManagedBuildOn(false);
          }
          cfg.setArtifactName(mProj.getDefaultArtifactName());
          CConfigurationData data = cfg.getConfigurationData();
          des.createConfiguration(ManagedBuildManager.CFG_DATA_PROVIDER_ID, data);
          monitor.worked(work);
        }
        mngr.setProjectDescription(project, des);
    }
  }
}
TOP

Related Classes of org.eclim.plugin.cdt.project.CProjectManager

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.