1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Merge remote-tracking branch 'cdt/master' into sd90

This commit is contained in:
Andrew Gvozdev 2013-03-16 15:02:32 -04:00
commit cd48acebff
113 changed files with 8432 additions and 1081 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010, 2012 Andrew Gvozdev and others.
* Copyright (c) 2010, 2013 Andrew Gvozdev 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
@ -8,7 +8,7 @@
* Contributors:
* Andrew Gvozdev - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.language.settings.providers.tests;
package org.eclipse.cdt.managedbuilder.language.settings.providers.tests;
import java.io.IOException;
import java.io.OutputStream;
@ -18,7 +18,14 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.envvar.EnvironmentVariable;
import org.eclipse.cdt.core.envvar.IContributedEnvironment;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.CIncludeFileEntry;
import org.eclipse.cdt.core.settings.model.CIncludePathEntry;
@ -34,7 +41,11 @@ import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.testplugin.ResourceHelper;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
import org.eclipse.cdt.internal.core.envvar.UserDefinedEnvironmentSupplier;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
import org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuiltinSpecsDetector;
import org.eclipse.cdt.utils.envvar.StorableEnvironment;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@ -54,15 +65,18 @@ public class BuiltinSpecsDetectorTest extends BaseTestCase {
private static final String CUSTOM_COMMAND_1 = "echo 1";
private static final String CUSTOM_COMMAND_2 = "echo 2";
private static final String ELEM_TEST = "test";
private static final String ENV_SAMPLE = "SAMPLE";
private static final String ENV_SAMPLE_VALUE_1 = "Sample Value 1";
private static final String ENV_SAMPLE_VALUE_2 = "Sample Value 2";
// those attributes must match that in AbstractBuiltinSpecsDetector
private static final String ATTR_PARAMETER = "parameter"; //$NON-NLS-1$
private static final String ATTR_CONSOLE = "console"; //$NON-NLS-1$
/**
* Mock built-in specs detector to test basic functionality of {@link AbstractBuiltinSpecsDetector}.
* Dummy to keep boilerplate code.
*/
private class MockBuiltinSpecsDetector extends AbstractBuiltinSpecsDetector {
private class DummyBuiltinSpecsDetector extends AbstractBuiltinSpecsDetector {
@Override
protected List<String> parseOptions(String line) {
return null;
@ -75,7 +89,12 @@ public class BuiltinSpecsDetectorTest extends BaseTestCase {
protected String getCompilerCommand(String languageId) {
return null;
}
}
/**
* Mock built-in specs detector to test basic functionality of {@link AbstractBuiltinSpecsDetector}.
*/
private class MockBuiltinSpecsDetector extends DummyBuiltinSpecsDetector {
@Override
protected void startupForLanguage(String languageId) throws CoreException {
super.startupForLanguage(languageId);
@ -89,20 +108,7 @@ public class BuiltinSpecsDetectorTest extends BaseTestCase {
/**
* Mock built-in specs detector to test execute() functionality.
*/
private class MockBuiltinSpecsDetectorExecutedFlag extends AbstractBuiltinSpecsDetector {
@Override
protected List<String> parseOptions(String line) {
return null;
}
@Override
protected AbstractOptionParser[] getOptionParsers() {
return null;
}
@Override
protected String getCompilerCommand(String languageId) {
return null;
}
private class MockBuiltinSpecsDetectorExecutedFlag extends DummyBuiltinSpecsDetector {
@Override
protected void execute() {
super.execute();
@ -116,6 +122,42 @@ public class BuiltinSpecsDetectorTest extends BaseTestCase {
}
}
/**
* Mock built-in specs detector to test environment change functionality.
*/
private class MockBuiltinSpecsDetectorEnvironmentChangeListener extends DummyBuiltinSpecsDetector {
private String sampleEnvVarValue = null;
@Override
protected boolean validateEnvironment() {
return false;
}
@Override
protected void execute() {
super.execute();
sampleEnvVarValue = environmentMap.get(ENV_SAMPLE);
}
@Override
public MockBuiltinSpecsDetectorEnvironmentChangeListener cloneShallow() throws CloneNotSupportedException {
MockBuiltinSpecsDetectorEnvironmentChangeListener clone = (MockBuiltinSpecsDetectorEnvironmentChangeListener) super.cloneShallow();
clone.sampleEnvVarValue = sampleEnvVarValue;
return clone;
}
@Override
public MockBuiltinSpecsDetectorEnvironmentChangeListener clone() throws CloneNotSupportedException {
MockBuiltinSpecsDetectorEnvironmentChangeListener clone = (MockBuiltinSpecsDetectorEnvironmentChangeListener) super.clone();
clone.sampleEnvVarValue = sampleEnvVarValue;
return clone;
}
protected boolean isExecuted() {
return isExecuted;
}
public String getSampleEnvVar() {
return sampleEnvVarValue;
}
}
/**
* Mock built-in specs detector to test parsing functionality.
*/
@ -508,6 +550,260 @@ public class BuiltinSpecsDetectorTest extends BaseTestCase {
assertEquals(expected, entries.get(0));
}
/**
* Test environment changes for provider registered to configuration.
*/
public void testAbstractBuiltinSpecsDetector_EnvChangesConfiguration_1() throws Exception {
// Create model project and accompanied descriptions
String projectName = getName();
IProject project = ResourceHelper.createCDTProjectWithConfig(projectName);
ICConfigurationDescription[] cfgDescriptions = getConfigurationDescriptions(project);
ICConfigurationDescription cfgDescription = cfgDescriptions[0];
// Create provider
MockBuiltinSpecsDetectorEnvironmentChangeListener provider = new MockBuiltinSpecsDetectorEnvironmentChangeListener();
// register environment listener on configuration - note that provider is not included in the configuration
provider.registerListener(cfgDescription);
try {
Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null);
} catch (Exception e) {
}
assertEquals(true, provider.isExecuted());
assertEquals(null, provider.getSampleEnvVar());
// unset "isExecuted" flag
provider.clear();
assertEquals(false, provider.isExecuted());
assertEquals(null, provider.getSampleEnvVar());
// Set an environment variable to the configuration
{
ICProjectDescription prjDescriptionWritable = CoreModel.getDefault().getProjectDescription(project, true);
ICConfigurationDescription cfgDescriptionWritable = prjDescriptionWritable.getActiveConfiguration();
// create and set sample environment variable in the configuration
IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
IContributedEnvironment contribEnv = envManager.getContributedEnvironment();
// Set an environment variable
IEnvironmentVariable var = new EnvironmentVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_1);
contribEnv.addVariable(var, cfgDescriptionWritable);
assertEquals(var, envManager.getVariable(ENV_SAMPLE, cfgDescriptionWritable, true));
CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable);
}
try {
Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null);
} catch (Exception e) {
}
// check if provider got executed with new value
assertEquals(true, provider.isExecuted());
assertEquals(ENV_SAMPLE_VALUE_1, provider.getSampleEnvVar());
// Repeat one more time with different value of environment variable
// unset "isExecuted" flag
provider.clear();
assertEquals(false, provider.isExecuted());
assertEquals(ENV_SAMPLE_VALUE_1, provider.getSampleEnvVar());
// Set an environment variable to the configuration
{
ICProjectDescription prjDescriptionWritable = CoreModel.getDefault().getProjectDescription(project, true);
ICConfigurationDescription cfgDescriptionWritable = prjDescriptionWritable.getActiveConfiguration();
// create and set sample environment variable in the configuration
IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
IContributedEnvironment contribEnv = envManager.getContributedEnvironment();
// Set an environment variable
IEnvironmentVariable var = new EnvironmentVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_2);
contribEnv.addVariable(var, cfgDescriptionWritable);
assertEquals(var, envManager.getVariable(ENV_SAMPLE, cfgDescriptionWritable, true));
CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable);
}
try {
Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null);
} catch (Exception e) {
}
// check if provider got executed with new value
assertEquals(true, provider.isExecuted());
assertEquals(ENV_SAMPLE_VALUE_2, provider.getSampleEnvVar());
// unregister listeners
provider.unregisterListener();
}
/**
* Test running on environment changes as provider assigned to a configuration.
*/
public void testAbstractBuiltinSpecsDetector_EnvChangesConfiguration_2() throws Exception {
// Create a project with one configuration
IProject project = ResourceHelper.createCDTProjectWithConfig(getName());
// Assign a provider to configuration
{
ICProjectDescription prjDescriptionWritable = CoreModel.getDefault().getProjectDescription(project, true);
ICConfigurationDescription cfgDescriptionWritable = prjDescriptionWritable.getActiveConfiguration();
// Create provider
MockBuiltinSpecsDetectorEnvironmentChangeListener provider = new MockBuiltinSpecsDetectorEnvironmentChangeListener();
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
providers.add(provider);
((ILanguageSettingsProvidersKeeper) cfgDescriptionWritable).setLanguageSettingProviders(providers);
// Write to project description
CProjectDescriptionManager.getInstance().setProjectDescription(project, prjDescriptionWritable);
try {
Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null);
} catch (Exception e) {
}
// Check that provider got executed
assertEquals(true, provider.isExecuted());
assertEquals(null, provider.getSampleEnvVar());
}
// Set environment variable to the configuration
{
ICProjectDescription prjDescriptionWritable = CoreModel.getDefault().getProjectDescription(project, true);
ICConfigurationDescription cfgDescriptionWritable = prjDescriptionWritable.getActiveConfiguration();
IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
IContributedEnvironment contribEnv = envManager.getContributedEnvironment();
// Set an environment variable
IEnvironmentVariable var = new EnvironmentVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_1);
contribEnv.addVariable(var, cfgDescriptionWritable);
assertEquals(var, envManager.getVariable(ENV_SAMPLE, cfgDescriptionWritable, true));
List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgDescriptionWritable).getLanguageSettingProviders();
MockBuiltinSpecsDetectorEnvironmentChangeListener provider = (MockBuiltinSpecsDetectorEnvironmentChangeListener) providers.get(0);
// unset "isExecuted" flag
provider.clear();
assertEquals(false, provider.isExecuted());
assertEquals(null, provider.getSampleEnvVar());
// Save project description including saving environment to the configuration
CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable);
}
try {
Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null);
} catch (Exception e) {
}
// Check if the provider got executed
{
// check if environment variable got there
ICProjectDescription prjDescription = CoreModel.getDefault().getProjectDescription(project, false);
ICConfigurationDescription cfgDescription = prjDescription.getActiveConfiguration();
IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
IEnvironmentVariable var = envManager.getVariable(ENV_SAMPLE, cfgDescription, true);
assertNotNull(var);
assertEquals(ENV_SAMPLE_VALUE_1, var.getValue());
// check if provider got executed with new value
List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
MockBuiltinSpecsDetectorEnvironmentChangeListener provider = (MockBuiltinSpecsDetectorEnvironmentChangeListener) providers.get(0);
assertEquals(true, provider.isExecuted());
assertEquals(ENV_SAMPLE_VALUE_1, provider.getSampleEnvVar());
}
// Repeat one more time with different value of environment variable
// Set another environment variable to the configuration
{
ICProjectDescription prjDescriptionWritable = CoreModel.getDefault().getProjectDescription(project, true);
ICConfigurationDescription cfgDescriptionWritable = prjDescriptionWritable.getActiveConfiguration();
IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
IContributedEnvironment contribEnv = envManager.getContributedEnvironment();
// Set an environment variable
IEnvironmentVariable var = new EnvironmentVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_2);
contribEnv.addVariable(var, cfgDescriptionWritable);
assertEquals(var, envManager.getVariable(ENV_SAMPLE, cfgDescriptionWritable, true));
List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgDescriptionWritable).getLanguageSettingProviders();
MockBuiltinSpecsDetectorEnvironmentChangeListener provider = (MockBuiltinSpecsDetectorEnvironmentChangeListener) providers.get(0);
// unset "isExecuted" flag
provider.clear();
assertEquals(false, provider.isExecuted());
assertEquals(ENV_SAMPLE_VALUE_1, provider.getSampleEnvVar());
// Save project description including saving environment to the configuration
CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable);
}
try {
Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null);
} catch (Exception e) {
}
// Check if the provider got executed
{
// check if environment variable got there
ICProjectDescription prjDescription = CoreModel.getDefault().getProjectDescription(project, false);
ICConfigurationDescription cfgDescription = prjDescription.getActiveConfiguration();
IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
IEnvironmentVariable var = envManager.getVariable(ENV_SAMPLE, cfgDescription, true);
assertNotNull(var);
assertEquals(ENV_SAMPLE_VALUE_2, var.getValue());
// check if provider got executed with new value
List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
MockBuiltinSpecsDetectorEnvironmentChangeListener provider = (MockBuiltinSpecsDetectorEnvironmentChangeListener) providers.get(0);
assertEquals(true, provider.isExecuted());
assertEquals(ENV_SAMPLE_VALUE_2, provider.getSampleEnvVar());
}
}
/**
* Test running on environment changes as global provider on workspace level.
*/
public void testAbstractBuiltinSpecsDetector_EnvChangesGlobal() throws Exception {
// Create provider
MockBuiltinSpecsDetectorEnvironmentChangeListener provider = new MockBuiltinSpecsDetectorEnvironmentChangeListener();
// register environment listener on workspace
provider.registerListener(null);
try {
Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null);
} catch (Exception e) {
}
assertEquals(true, provider.isExecuted());
assertEquals(null, provider.getSampleEnvVar());
// unset "isExecuted" flag
provider.clear();
assertEquals(false, provider.isExecuted());
assertEquals(null, provider.getSampleEnvVar());
// create and set sample environment variable in the workspace
UserDefinedEnvironmentSupplier fUserSupplier = EnvironmentVariableManager.fUserSupplier;
StorableEnvironment vars = fUserSupplier.getWorkspaceEnvironmentCopy();
vars.createVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_1);
fUserSupplier.setWorkspaceEnvironment(vars);
try {
Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null);
} catch (Exception e) {
}
// check if provider got executed with new value
assertEquals(true, provider.isExecuted());
assertEquals(ENV_SAMPLE_VALUE_1, provider.getSampleEnvVar());
provider.clear();
// create and set sample environment variable in the workspace
vars.deleteAll();
vars.createVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_2);
fUserSupplier.setWorkspaceEnvironment(vars);
try {
Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null);
} catch (Exception e) {
}
// check if provider got executed with new value
assertEquals(true, provider.isExecuted());
assertEquals(ENV_SAMPLE_VALUE_2, provider.getSampleEnvVar());
// unregister listeners
provider.unregisterListener();
}
/**
* Check that entries get grouped by kinds by stock built-in specs detector.
*/

View file

@ -46,9 +46,12 @@ import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.internal.core.BuildRunnerHelper;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedMakeMessages;
import org.eclipse.cdt.utils.CommandLineUtil;
import org.eclipse.cdt.utils.envvar.IEnvironmentChangeEvent;
import org.eclipse.cdt.utils.envvar.IEnvironmentChangeListener;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
@ -83,7 +86,9 @@ import org.w3c.dom.Element;
*
* @since 8.1
*/
public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSettingsOutputScanner implements ICListenerAgent {
public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSettingsOutputScanner
implements ICListenerAgent, IEnvironmentChangeListener {
public static final String JOB_FAMILY_BUILTIN_SPECS_DETECTOR = "org.eclipse.cdt.managedbuilder.AbstractBuiltinSpecsDetector"; //$NON-NLS-1$
protected static final String COMPILER_MACRO = "${COMMAND}"; //$NON-NLS-1$
@ -345,11 +350,21 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti
@Override
public void registerListener(ICConfigurationDescription cfgDescription) {
currentCfgDescription = cfgDescription;
EnvironmentVariableManager.fUserSupplier.registerEnvironmentChangeListener(this);
execute();
}
@Override
public void unregisterListener() {
EnvironmentVariableManager.fUserSupplier.unregisterEnvironmentChangeListener(this);
}
/** @since 8.2 */
@Override
public void handleEvent(IEnvironmentChangeEvent event) {
// here comes workspace environment change
execute();
}
@Override

View file

@ -1,195 +1,104 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 QNX Software Systems and others.
* Copyright (c) 2006, 2013 QNX Software Systems 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:
* QNX Software Systems - Initial API and implementation
* Doug Schaefer, QNX Software Systems - Initial API and implementation
* Andrew Gvozdev - Ability to use different MinGW versions in different cfg
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.gnu.mingw;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.internal.core.MinGW;
import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.envvar.IBuildEnvironmentVariable;
import org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSupplier;
import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider;
import org.eclipse.cdt.utils.PathUtil;
import org.eclipse.cdt.managedbuilder.internal.envvar.BuildEnvVar;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
/**
* @author Doug Schaefer
*
* @noextend This class is not intended to be subclassed by clients.
*/
public class MingwEnvironmentVariableSupplier implements IConfigurationEnvironmentVariableSupplier {
private static final String ENV_PATH = "PATH"; //$NON-NLS-1$
private static String envPathValueCached = null;
private static String envMingwHomeValueCached = null;
private static IPath binDir = null;
private static IPath msysBinDir = null;
private static class MingwBuildEnvironmentVariable implements IBuildEnvironmentVariable {
private static final String PATH_SEPARATOR = ";"; //$NON-NLS-1$
private final String name;
private final String value;
private final int operation;
public MingwBuildEnvironmentVariable(String name, String value, int operation) {
this.name = name;
this.value = value;
this.operation = operation;
}
@Override
public String getName() {
return name;
}
@Override
public String getValue() {
return value;
}
@Override
public int getOperation() {
return operation;
}
@Override
public String getDelimiter() {
return PATH_SEPARATOR;
}
}
private static final String BACKSLASH = java.io.File.separator;
private static final String PATH_DELIMITER = EnvironmentVariableManager.getDefault().getDefaultDelimiter();
/**
* @return location of $MINGW_HOME/bin folder on the file-system.
* @deprecated. Deprecated as of CDT 8.2. Note that MinGW root path in general may depend on configuration.
*
* If you use this do not cache results to ensure user preferences are accounted for.
* Please rely on internal caching.
*/
@Deprecated
public static IPath getBinDir() {
locateMingw();
IPath binDir = null;
String minGWHome = MinGW.getMinGWHome();
if (minGWHome != null) {
binDir = new Path(minGWHome).append("bin"); //$NON-NLS-1$
}
return binDir;
}
/**
* @return location of $MINGW_HOME/msys/bin folder on the file-system.
* @deprecated. Deprecated as of CDT 8.2. Note that MinGW root path in general may depend on configuration.
*
* If you use this do not cache results to ensure user preferences are accounted for.
* Please rely on internal caching.
*/
@Deprecated
public static IPath getMsysBinDir() {
locateMingw();
IPath msysBinDir = null;
String msysHome = MinGW.getMSysHome();
if (msysHome != null) {
msysBinDir = new Path(msysHome).append("bin"); //$NON-NLS-1$
}
return msysBinDir;
}
/**
* Locate MinGW directories. The results are judicially cached so it is reasonably cheap to call.
* The reason to call it each time is to check if user changed environment in preferences.
*/
private static void locateMingw() {
IEnvironmentVariable varPath = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(ENV_PATH, null, true);
String envPathValue = varPath != null ? varPath.getValue() : null;
IEnvironmentVariable varMingwHome = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable("MINGW_HOME", null, true); //$NON-NLS-1$
String envMingwHomeValue = varMingwHome != null ? varMingwHome.getValue() : null;
if (CDataUtil.objectsEqual(envPathValue, envPathValueCached) && CDataUtil.objectsEqual(envMingwHomeValue, envMingwHomeValueCached)) {
return;
}
envPathValueCached = envPathValue;
envMingwHomeValueCached = envMingwHomeValue;
binDir = locateBinDir();
msysBinDir = locateMsysBinDir(binDir);
}
private static IPath locateBinDir() {
// Check $MINGW_HOME
IPath mingwBinDir = new Path(envMingwHomeValueCached + "\\bin"); //$NON-NLS-1$
if (mingwBinDir.toFile().isDirectory()) {
return mingwBinDir;
}
// Try the mingw directory in the platform install directory
// CDT distributions like Wascana may distribute MinGW like that
IPath installPath = new Path(Platform.getInstallLocation().getURL().getFile());
mingwBinDir = installPath.append("mingw\\bin"); //$NON-NLS-1$
if (mingwBinDir.toFile().isDirectory()) {
return mingwBinDir;
}
// Check for MinGW-w64 on Windows 64 bit, see http://mingw-w64.sourceforge.net/
if (Platform.ARCH_X86_64.equals(Platform.getOSArch())) {
IPath gcc64Loc = PathUtil.findProgramLocation("x86_64-w64-mingw32-gcc.exe", envPathValueCached); //$NON-NLS-1$
if (gcc64Loc != null) {
return gcc64Loc.removeLastSegments(1);
}
}
// Look in PATH values. Look for mingw32-gcc.exe
// TODO: Since this dir is already in the PATH, why are we adding it here?
// This is really only to support isToolchainAvail. Must be a better way.
// AG: Because otherwise the toolchain won't be shown in the list of "supported" toolchains in UI
// when MinGW installed in custom location even if it is in the PATH
IPath gccLoc = PathUtil.findProgramLocation("mingw32-gcc.exe", envPathValueCached); //$NON-NLS-1$
if (gccLoc != null) {
return gccLoc.removeLastSegments(1);
}
// Try the default MinGW install dir
mingwBinDir = new Path("C:\\MinGW\\bin"); //$NON-NLS-1$
if (mingwBinDir.toFile().isDirectory()) {
return mingwBinDir;
}
return null;
}
private static IPath locateMsysBinDir(IPath binPath) {
if (binPath != null) {
// Just look in the install location parent dir
IPath installPath = new Path(Platform.getInstallLocation().getURL().getFile());
IPath msysBinPath = installPath.append("msys\\bin"); //$NON-NLS-1$
if (msysBinPath.toFile().isDirectory()) {
return msysBinPath;
}
if (envMingwHomeValueCached != null) {
msysBinPath = new Path(envMingwHomeValueCached + "\\msys\\1.0\\bin"); //$NON-NLS-1$
if (msysBinPath.toFile().isDirectory()) {
return msysBinPath;
}
}
// Try the new MinGW msys bin dir
msysBinPath = new Path("C:\\MinGW\\msys\\1.0\\bin"); //$NON-NLS-1$
if (msysBinPath.toFile().isDirectory()) {
return msysBinPath;
}
}
return null;
}
@Override
public IBuildEnvironmentVariable getVariable(String variableName, IConfiguration configuration, IEnvironmentVariableProvider provider) {
if (variableName.equals(ENV_PATH)) {
locateMingw();
if (binDir != null) {
String pathStr = binDir.toOSString();
if (msysBinDir != null) {
pathStr += MingwBuildEnvironmentVariable.PATH_SEPARATOR + msysBinDir.toOSString();
if (variableName.equals(MinGW.ENV_MINGW_HOME)) {
IEnvironmentVariable varMinGWHome = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(MinGW.ENV_MINGW_HOME, null, false);
if (varMinGWHome == null) {
// Contribute if the variable does not already come from workspace environment
String minGWHome = MinGW.getMinGWHome();
if (minGWHome == null) {
// If the variable is not defined still show it in the environment variables list as a hint to user
minGWHome = ""; //$NON-NLS-1$
}
return new MingwBuildEnvironmentVariable(ENV_PATH, pathStr, IBuildEnvironmentVariable.ENVVAR_PREPEND);
return new BuildEnvVar(MinGW.ENV_MINGW_HOME, new Path(minGWHome).toOSString(), IBuildEnvironmentVariable.ENVVAR_REPLACE);
}
return null;
} else if (variableName.equals(MinGW.ENV_MSYS_HOME)) {
IEnvironmentVariable varMsysHome = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(MinGW.ENV_MSYS_HOME, null, false);
if (varMsysHome == null) {
// Contribute if the variable does not already come from workspace environment
String msysHome = MinGW.getMSysHome();
if (msysHome == null) {
// If the variable is not defined still show it in the environment variables list as a hint to user
msysHome = ""; //$NON-NLS-1$
}
return new BuildEnvVar(MinGW.ENV_MSYS_HOME, new Path(msysHome).toOSString(), IBuildEnvironmentVariable.ENVVAR_REPLACE);
}
return null;
} else if (variableName.equals(ENV_PATH)) {
@SuppressWarnings("nls")
String path = "${" + MinGW.ENV_MINGW_HOME + "}" + BACKSLASH + "bin" + PATH_DELIMITER
+ "${" + MinGW.ENV_MSYS_HOME + "}" + BACKSLASH + "bin";
return new BuildEnvVar(ENV_PATH, path, IBuildEnvironmentVariable.ENVVAR_PREPEND);
}
return null;
@ -197,10 +106,11 @@ public class MingwEnvironmentVariableSupplier implements IConfigurationEnvironme
@Override
public IBuildEnvironmentVariable[] getVariables(IConfiguration configuration, IEnvironmentVariableProvider provider) {
IBuildEnvironmentVariable path = getVariable(ENV_PATH, configuration, provider);
return path != null
? new IBuildEnvironmentVariable[] { path }
: new IBuildEnvironmentVariable[0];
return new IBuildEnvironmentVariable[] {
getVariable(MinGW.ENV_MINGW_HOME, configuration, provider),
getVariable(MinGW.ENV_MSYS_HOME, configuration, provider),
getVariable(ENV_PATH, configuration, provider),
};
}
}

View file

@ -1,30 +1,35 @@
/**********************************************************************
* Copyright (c) 2007, 2010 QNX Software Systems and others.
* Copyright (c) 2007, 2013 QNX Software Systems 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:
* QNX Software Systems - Initial API and implementation
* Doug Schaefer (QNX Software Systems) - Initial API and implementation
* Andrew Gvozdev - Ability to use different MinGW versions in different cfg
**********************************************************************/
package org.eclipse.cdt.managedbuilder.gnu.mingw;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.internal.core.MinGW;
import org.eclipse.cdt.managedbuilder.core.IManagedIsToolChainSupported;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
import org.eclipse.cdt.managedbuilder.internal.envvar.EnvironmentVariableManagerToolChain;
import org.osgi.framework.Version;
/**
* @author Doug Schaefer
*
* @noextend This class is not intended to be subclassed by clients.
*/
public class MingwIsToolChainSupported implements IManagedIsToolChainSupported {
private static final String ENV_PATH = "PATH"; //$NON-NLS-1$
@Override
public boolean isSupported(IToolChain toolChain, Version version, String instance) {
// Only supported if we can find the mingw bin dir to run the compiler
return MingwEnvironmentVariableSupplier.getBinDir() != null;
IEnvironmentVariable var = new EnvironmentVariableManagerToolChain(toolChain).getVariable(ENV_PATH, true);
String envPath = var != null ? var.getValue() : null;
return MinGW.isAvailable(envPath);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2009, 2010 Broadcom Corp. and others.
* Copyright (c) 2009, 2013 Broadcom Corp. 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
@ -11,6 +11,7 @@
package org.eclipse.cdt.core.envvar;
import java.io.ByteArrayInputStream;
import java.util.Arrays;
import junit.framework.Test;
import junit.framework.TestCase;
@ -22,6 +23,9 @@ import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.core.testplugin.ResourceHelper;
import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
import org.eclipse.cdt.utils.envvar.IEnvironmentChangeEvent;
import org.eclipse.cdt.utils.envvar.IEnvironmentChangeListener;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
@ -31,6 +35,29 @@ import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
public class IEnvironmentVariableManagerTests extends TestCase {
/**
* Mock listener to listen to environment variable change events.
*/
private class MockEnvironmentListener implements IEnvironmentChangeListener {
private int count = 0;
private IEnvironmentChangeEvent lastEvent = null;
public int getCount() {
return count;
}
public void resetCount() {
count = 0;
lastEvent = null;
}
public IEnvironmentChangeEvent getLastEvent() {
return lastEvent;
}
@Override
public void handleEvent(IEnvironmentChangeEvent event) {
count++;
lastEvent = event;
}
}
@Override
protected void setUp() throws Exception {
@ -639,4 +666,88 @@ public class IEnvironmentVariableManagerTests extends TestCase {
assertEquals(varInvalidListValue,varInvalidList.getValue());
}
/**
* Test case to test environment variable change notifications
*
* @throws Exception
*/
public void testEnvironmentChangeListener() throws Exception {
// Register environment event listener
MockEnvironmentListener envListener = new MockEnvironmentListener();
EnvironmentVariableManager.fUserSupplier.registerEnvironmentChangeListener(envListener);
assertEquals(0, envListener.getCount());
// Define sample environment variable name
String variableName = "VAR";
// Test adding a variable
IEnvironmentVariable[] varsAdded = { new EnvironmentVariable(variableName, "value") };
{
// Reset the listener
envListener.resetCount();
assertEquals(0, envListener.getCount());
// Add environment variable
EnvironmentVariableManager.fUserSupplier.setVariables(varsAdded, null);
EnvironmentVariableManager.fUserSupplier.storeWorkspaceEnvironment(true);
// Doublecheck that variable added
IEnvironmentVariable[] actualVars = EnvironmentVariableManager.fUserSupplier.getVariables(null);
assertTrue(((Arrays.equals(varsAdded, actualVars))));
// Check event received by the listener
assertEquals(1, envListener.getCount());
IEnvironmentChangeEvent event = envListener.getLastEvent();
assertTrue(Arrays.equals(new IEnvironmentVariable[0], event.getOldVariables()));
assertTrue(Arrays.equals(varsAdded, event.getNewVariables()));
}
// Test changing a variable
IEnvironmentVariable[] varsChanged = { new EnvironmentVariable(variableName, "value-changed") };
{
// Reset the listener
envListener.resetCount();
assertEquals(0, envListener.getCount());
// Add environment variable
EnvironmentVariableManager.fUserSupplier.setVariables(varsChanged, null);
EnvironmentVariableManager.fUserSupplier.storeWorkspaceEnvironment(true);
// Doublecheck that variable added
IEnvironmentVariable[] actualVars = EnvironmentVariableManager.fUserSupplier.getVariables(null);
assertTrue(Arrays.equals(varsChanged, actualVars));
// Check event received by the listener
assertEquals(1, envListener.getCount());
IEnvironmentChangeEvent event = envListener.getLastEvent();
assertTrue(Arrays.equals(varsAdded, event.getOldVariables()));
assertTrue(Arrays.equals(varsChanged, event.getNewVariables()));
}
// Test removing a variable
IEnvironmentVariable[] varsRemoved = {};
{
// Reset the listener
envListener.resetCount();
assertEquals(0, envListener.getCount());
// Add environment variable
EnvironmentVariableManager.fUserSupplier.setVariables(varsRemoved, null);
EnvironmentVariableManager.fUserSupplier.storeWorkspaceEnvironment(true);
// Doublecheck that variable added
IEnvironmentVariable[] actualVars = EnvironmentVariableManager.fUserSupplier.getVariables(null);
assertTrue(Arrays.equals(varsRemoved, actualVars));
// Check event received by the listener
assertEquals(1, envListener.getCount());
IEnvironmentChangeEvent event = envListener.getLastEvent();
assertTrue(Arrays.equals(varsChanged, event.getOldVariables()));
assertTrue(Arrays.equals(varsRemoved, event.getNewVariables()));
}
// Release environment event listener
EnvironmentVariableManager.fUserSupplier.unregisterEnvironmentChangeListener(envListener);
}
}

View file

@ -7539,10 +7539,47 @@ public class AST2TemplateTests extends AST2TestBase {
// void foo(T t) {
// bar(t);
// }
public void testUnqualifiedFunctionCallInTemplate_402498() throws Exception {
public void testUnqualifiedFunctionCallInTemplate_402498a() throws Exception {
parseAndCheckBindings();
}
// template <typename T>
// auto foo(T t) -> decltype(bar(t));
//
// namespace N {
// class A {};
// int bar(A);
// }
//
// int main() {
// auto x = foo(N::A());
// }
public void testUnqualifiedFunctionCallInTemplate_402498b() throws Exception {
new BindingAssertionHelper(getAboveComment(), true).assertVariableType("x", CommonTypes.int_);
}
// template <typename T>
// auto foo(T t) -> decltype(bar(t));
//
// namespace N {
// class A {};
// }
//
// int bar(A);
//
// int main() {
// auto x = foo(N::A());
// }
public void testUnqualifiedFunctionCallInTemplate_402498c() throws Exception {
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
ICPPVariable x = helper.assertNonProblem("x", ICPPVariable.class);
// We really should assert that x's type is a ProblemType, but the semantic
// analyzer is too lenient and makes it a TypeOfDependentExpression if it
// can't instantiate the return type of foo() properly.
// That's another bug for another day.
assertFalse(x.getType().isSameType(CommonTypes.int_));
}
// template <typename>
// struct no_type {};
//

View file

@ -29,14 +29,14 @@ public class CommentTests extends AST2TestBase {
return suite(CommentTests.class);
}
public void testCountCommentsInHeaderFile() throws ParserException{
public void testCountCommentsInHeaderFile() throws ParserException {
IASTTranslationUnit tu = parse(getHSource(), ParserLanguage.CPP, false, true);
IASTComment[] comments = tu.getComments();
assertEquals(9, comments.length);
}
public void testCommentsInHeaderFile() throws ParserException{
public void testCommentsInHeaderFile() throws ParserException {
IASTTranslationUnit tu = parse(getHSource(), ParserLanguage.CPP, false, true);
IASTComment[] comments = tu.getComments();
@ -51,14 +51,14 @@ public class CommentTests extends AST2TestBase {
assertEquals("//Endcomment h", new String(comments[8].getComment()));
}
public void testCountCommentsInCPPFile() throws ParserException{
public void testCountCommentsInCPPFile() throws ParserException {
IASTTranslationUnit tu = parse(getCppSource(), ParserLanguage.CPP, false, true);
IASTComment[] comments = tu.getComments();
assertEquals(10, comments.length);
}
public void testCommentsInCPPFile() throws ParserException{
public void testCommentsInCPPFile() throws ParserException {
IASTTranslationUnit tu = parse(getCppSource(), ParserLanguage.CPP, false, true);
IASTComment[] comments = tu.getComments();
@ -74,14 +74,14 @@ public class CommentTests extends AST2TestBase {
assertEquals("//An integer", new String(comments[9].getComment()));
}
public void testCountCommentsInCFile() throws ParserException{
public void testCountCommentsInCFile() throws ParserException {
IASTTranslationUnit tu = parse(getCSource(), ParserLanguage.C, false, true);
IASTComment[] comments = tu.getComments();
assertEquals(4, comments.length);
}
public void testCommentsInCFile() throws ParserException{
public void testCommentsInCFile() throws ParserException {
IASTTranslationUnit tu = parse(getCSource(), ParserLanguage.C, false, true);
IASTComment[] comments = tu.getComments();
@ -211,7 +211,7 @@ public class CommentTests extends AST2TestBase {
}
// //comment
public void testCommentLocation_bug186337() throws Exception{
public void testCommentLocation_bug186337() throws Exception {
CharSequence code= getContents(1)[0];
IASTTranslationUnit tu = parse(code.toString(), ParserLanguage.CPP, false, true);
IASTComment[] comments = tu.getComments();
@ -234,7 +234,6 @@ public class CommentTests extends AST2TestBase {
// #ifdef WHATEVA // TODO: ignored
// #endif // TODO: ignored
// // TODO: shows up in task list
public void testCommentInDirectives_bug192546() throws Exception {
CharSequence code= getContents(1)[0];
IASTTranslationUnit tu = parse(code.toString(), ParserLanguage.CPP, false, false);

View file

@ -30,6 +30,7 @@ import org.eclipse.cdt.core.parser.tests.rewrite.TestSourceFile;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.ASTCommenter;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
/**
* This test tests the behavior of the class ASTCommenter. It checks if the ASTCommenter assigns
@ -158,15 +159,17 @@ public class CommentHandlingTest extends RewriteBaseTest {
return output.toString().trim();
}
private String getSignature(IASTNode actNode) {
if (actNode instanceof IASTCompositeTypeSpecifier) {
IASTCompositeTypeSpecifier comp = (IASTCompositeTypeSpecifier) actNode;
private String getSignature(IASTNode node) {
if (node instanceof IASTCompositeTypeSpecifier) {
IASTCompositeTypeSpecifier comp = (IASTCompositeTypeSpecifier) node;
return comp.getName().toString();
} else if (actNode instanceof IASTEnumerationSpecifier) {
IASTEnumerationSpecifier comp = (IASTEnumerationSpecifier) actNode;
} else if (node instanceof IASTEnumerationSpecifier) {
IASTEnumerationSpecifier comp = (IASTEnumerationSpecifier) node;
return comp.getName().toString();
} else if (node instanceof IASTTranslationUnit) {
return Path.fromOSString(node.getFileLocation().getFileName()).lastSegment();
}
return actNode.getRawSignature();
return node.getRawSignature();
}
private static String getSeparatingRegexp() {

View file

@ -61,7 +61,7 @@ Export-Package: org.eclipse.cdt.core,
org.eclipse.cdt.internal.core.dom.rewrite;x-friends:="org.eclipse.cdt.core.tests,org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.dom.rewrite.astwriter;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.dom.rewrite.changegenerator;x-internal:=true,
org.eclipse.cdt.internal.core.dom.rewrite.commenthandler;x-internal:=true,
org.eclipse.cdt.internal.core.dom.rewrite.commenthandler;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.dom.rewrite.util;x-internal:=true,
org.eclipse.cdt.internal.core.envvar;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.managedbuilder.core",
org.eclipse.cdt.internal.core.index;x-friends:="org.eclipse.cdt.ui",

View file

@ -37,25 +37,25 @@ public interface IASTFileLocation extends IASTNodeLocation {
public int getNodeLength();
/**
* Get the starting line number. Locations obtained via the index do not have line numbers
* and return <code>0</code>.
* Returns the starting line number. Locations obtained via the index do not have line numbers
* and return {@code 0}.
*
* @return int representing line number or <code>0</code> if not applicable
* @return the 1-based line number, or {@code 0} if not applicable
*/
public int getStartingLineNumber();
/**
* Get the ending line number. Locations obtained via the index do not have line numbers
* and return <code>0</code>.
* Returns the ending line number. Locations obtained via the index do not have line numbers
* and return {@code 0}.
*
* @return int representing line number or <code>0</code> if not applicable
* @return the 1-based line number, or {@code 0} if not applicable
*/
public int getEndingLineNumber();
/**
* Returns the inclusion statement that included this file, or <code>null</code> for
* a top-level file.
* Also <code>null</code> when the file location does not belong to an AST node, e.g.
* Also {@code null} when the file location does not belong to an AST node, e.g.
* if it is obtained from a name in the index.
* @since 5.4
*/

View file

@ -11,8 +11,8 @@
package org.eclipse.cdt.core.dom.ast;
/**
* The for statement. The initialization clause can be an expression or a
* declaration but not both.
* The 'for' statement. The initialization clause can be an expression
* or a declaration but not both.
*
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
@ -57,8 +57,7 @@ public interface IASTForStatement extends IASTStatement {
* @param statement
*/
public void setInitializerStatement( IASTStatement statement );
/**
* Get the condition expression for the loop.
*

View file

@ -32,7 +32,7 @@ public interface IASTIdExpression extends IASTExpression, IASTNameOwner {
public IASTName getName();
/**
* Set the name to be used inthe expression.
* Sets the name to be used in the expression.
*
* @param name
*/

View file

@ -23,16 +23,14 @@ import org.eclipse.cdt.core.parser.ISignificantMacros;
*/
public interface IASTPreprocessorIncludeStatement extends IASTPreprocessorStatement, IFileNomination {
/**
* <code>INCLUDE_NAME</code> describes the relationship between an include directive and
* it's name.
* {@code INCLUDE_NAME} describes the relationship between an include directive and its name.
*/
public static final ASTNodeProperty INCLUDE_NAME = new ASTNodeProperty(
"IASTPreprocessorMacroDefinition.INCLUDE_NAME - Include Name"); //$NON-NLS-1$
/**
* Returns the absolute location of the file found through #include.
* Only valid if {@link #isResolved()} returns <code>true</code>.
* Returns the absolute location of the file found through #include, or an empty string if
* include was not resolved.
*/
public String getPath();
@ -109,14 +107,14 @@ public interface IASTPreprocessorIncludeStatement extends IASTPreprocessorStatem
public boolean isErrorInIncludedFile();
/**
* Returns true, if an attempt will be or has been made to create AST for the target
* Returns {@code true}, if an attempt will be or has been made to create AST for the target
* of this inclusion.
* @since 5.4
*/
public boolean createsAST();
/**
* Returns the file from the index that this include statement has pulled in, or <code>null</code>
* Returns the file from the index that this include statement has pulled in, or {@code null}
* if the include creates AST or is unresolved or skipped.
* @since 5.4
*/

View file

@ -32,26 +32,37 @@ import org.eclipse.core.runtime.IAdaptable;
*/
public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomination, IAdaptable {
/**
* <code>OWNED_DECLARATION</code> represents the relationship between an <code>IASTTranslationUnit</code> and
* it's nested <code>IASTDeclaration</code>'s.
* {@code OWNED_DECLARATION} represents the relationship between an {@code IASTTranslationUnit}
* and its nested {@code IASTDeclaration}'s.
*/
public static final ASTNodeProperty OWNED_DECLARATION = new ASTNodeProperty(
"IASTTranslationUnit.OWNED_DECLARATION - IASTDeclaration for IASTTranslationUnit"); //$NON-NLS-1$
/**
* <code>SCANNER_PROBLEM</code> represents the relationship between an <code>IASTTranslationUnit</code> and
* it's nested <code>IASTProblem</code>.
* {@code SCANNER_PROBLEM} represents the relationship between an {@code IASTTranslationUnit}
* and its nested {@code IASTProblem}.
*/
public static final ASTNodeProperty SCANNER_PROBLEM = new ASTNodeProperty(
"IASTTranslationUnit.SCANNER_PROBLEM - IASTProblem (scanner caused) for IASTTranslationUnit"); //$NON-NLS-1$
/**
* <code>PREPROCESSOR_STATEMENT</code> represents the relationship between an <code>IASTTranslationUnit</code> and
* it's nested <code>IASTPreprocessorStatement</code>.
* {@code PREPROCESSOR_STATEMENT} represents the relationship between
* an {@code IASTTranslationUnit} and its nested {@code IASTPreprocessorStatement}.
*/
public static final ASTNodeProperty PREPROCESSOR_STATEMENT = new ASTNodeProperty(
"IASTTranslationUnit.PREPROCESSOR_STATEMENT - IASTPreprocessorStatement for IASTTranslationUnit"); //$NON-NLS-1$
public static final ASTNodeProperty MACRO_EXPANSION = new ASTNodeProperty(
"IASTTranslationUnit.MACRO_EXPANSION - IASTPreprocessorMacroExpansion node for macro expansions."); //$NON-NLS-1$
/**
* @deprecated names for macro expansions are nested inside of
* {@link IASTPreprocessorMacroExpansion}.
*/
@Deprecated
public static final ASTNodeProperty EXPANSION_NAME = new ASTNodeProperty(
"IASTTranslationUnit.EXPANSION_NAME - IASTName generated for macro expansions."); //$NON-NLS-1$
/**
* A translation unit contains an ordered sequence of declarations.
*
@ -62,7 +73,7 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomi
/**
* Adds declaration to translation unit.
*
* @param declaration <code>IASTDeclaration</code>
* @param declaration {@code IASTDeclaration}
*/
@Override
public void addDeclaration(IASTDeclaration declaration);
@ -130,7 +141,7 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomi
* The object is suitable for working in one of the files that is part of
* the translation unit.
* @param filePath file of interest, as returned by {@link IASTFileLocation#getFileName()},
* or <code>null</code> to specify the root source of the translation-unit.
* or {@code null} to specify the root source of the translation-unit.
* @return an IASTNodeSelector.
* @since 5.0
*/
@ -158,8 +169,8 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomi
public IASTPreprocessorMacroDefinition[] getBuiltinMacroDefinitions();
/**
* Returns the include directives encountered in parsing this translation unit. This will also contain directives
* used for handling the gcc-options -imacros and -include.
* Returns the include directives encountered in parsing this translation unit. This will also
* contain directives used for handling the gcc-options -imacros and -include.
* <p>
* In case the information for a header-file is pulled in from the index,
* include directives contained therein are not returned.
@ -180,7 +191,7 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomi
/**
* Returns all preprocessor and scanner problems.
* @return <code>IASTProblem[]</code>
* @return {@code IASTProblem[]}
*/
public IASTProblem[] getPreprocessorProblems();
@ -199,21 +210,11 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomi
/**
* Flattens the node locations provided into a single file location.
*
* @param nodeLocations <code>IASTNodeLocation</code>s to flatten
* @param nodeLocations {@code IASTNodeLocation}s to flatten
* @return null if not possible, otherwise, a file location representing where the macros are.
*/
public IASTFileLocation flattenLocationsToFile(IASTNodeLocation[] nodeLocations);
/**
* @deprecated names for macro expansions are nested inside of {@link IASTPreprocessorMacroExpansion}.
*/
@Deprecated
public static final ASTNodeProperty EXPANSION_NAME = new ASTNodeProperty(
"IASTTranslationUnit.EXPANSION_NAME - IASTName generated for macro expansions."); //$NON-NLS-1$
public static final ASTNodeProperty MACRO_EXPANSION = new ASTNodeProperty(
"IASTTranslationUnit.MACRO_EXPANSION - IASTPreprocessorMacroExpansion node for macro expansions."); //$NON-NLS-1$
public static interface IDependencyTree {
public String getTranslationUnitPath();
@ -253,7 +254,7 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomi
/**
* Return the set of files that have been skipped because they have been part of the index
* prior to creating this AST, or <code>null</code> if not available.
* prior to creating this AST, or {@code null} if not available.
* Applies only, if AST was created with an index and the option to skip headers found in
* the index.
* @since 5.1
@ -261,7 +262,7 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomi
IIndexFileSet getIndexFileSet();
/**
* Return the set of files in the index that are superseded by this AST, or <code>null</code>
* Return the set of files in the index that are superseded by this AST, or {@code null}
* if not available. Applies only, if AST was created with an index.
* @since 5.3
*/
@ -271,7 +272,7 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomi
* In case the AST was created in a way that supports comment parsing, all comments of
* the translation unit are returned. Otherwise an empty array will be supplied.
*
* @return <code>IASTComment[]</code>
* @return {@code IASTComment[]}
* @since 4.0
*/
public IASTComment[] getComments();
@ -339,7 +340,7 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomi
public IASTTranslationUnit copy(CopyStyle style);
/**
* Returns the ITranslationUnit this AST originated from, or <code>null</code> if the AST
* Returns the ITranslationUnit this AST originated from, or {@code null} if the AST
* does not correspond to an ITranslationUnit.
*
* @since 5.3

View file

@ -15,14 +15,16 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
/**
*
* The C++ 'for' statement.
*
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPASTForStatement extends IASTForStatement {
public static final ASTNodeProperty CONDITION_DECLARATION = new ASTNodeProperty( "org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement"); //$NON-NLS-1$
public void setConditionDeclaration( IASTDeclaration d );
public static final ASTNodeProperty CONDITION_DECLARATION =
new ASTNodeProperty("org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement"); //$NON-NLS-1$
public void setConditionDeclaration(IASTDeclaration d);
public IASTDeclaration getConditionDeclaration();
/**

View file

@ -6,8 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
@ -24,7 +24,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPBase extends Cloneable {
public static final ICPPBase[] EMPTY_BASE_ARRAY = new ICPPBase[0];
public static final ICPPBase[] EMPTY_BASE_ARRAY = {};
public static final int v_private = ICPPASTBaseSpecifier.v_private;
public static final int v_protected = ICPPASTBaseSpecifier.v_protected;

View file

@ -28,7 +28,7 @@ public interface ICPPEnumeration extends IEnumeration, ICPPBinding {
boolean isScoped();
/**
* Returns the underlying type of the enumeration if it is fixed, or <code>null</code> otherwise.
* Returns the underlying type of the enumeration if it is fixed, or {@code null} otherwise.
* The underlying type can only be fixed in C++.
*/
IType getFixedType();

View file

@ -74,6 +74,21 @@ public class CharArrayUtils {
return true;
}
/**
* Returns {@code true} if the contents of a section of a character array are the same as
* contents of a string.
* @since 5.5
*/
public static final boolean equals(char[] str1, int start1, int length1, String str2) {
if (length1 != str2.length() || str1.length < length1 + start1)
return false;
for (int i = 0; i < length1; ++i) {
if (str1[start1++] != str2.charAt(i))
return false;
}
return true;
}
/**
* Returns {@code true} if a prefix of the character array is the same as contents
* of a string.
@ -117,6 +132,10 @@ public class CharArrayUtils {
return str1.length - str2.length;
}
/**
* Returns {@code true} if the contents of a section of a character array are the same as
* contents of another character array.
*/
public static final boolean equals(char[] str1, int start1, int length1, char[] str2) {
if (length1 != str2.length || str1.length < length1 + start1)
return false;

View file

@ -485,4 +485,52 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
}
return fSizeofCalculator;
}
/**
* Returns the offset of the given node, or -1 if the node is not part of the translation
* unit file or doesn't have a file-location.
* @see IASTNode#getFileLocation()
*/
public static int getNodeOffset(IASTNode node) {
if (!node.isPartOfTranslationUnitFile())
return -1;
IASTFileLocation nodeLocation = node.getFileLocation();
return nodeLocation != null ? nodeLocation.getNodeOffset() : -1;
}
/**
* Returns the end offset of the given node, or -1 if the node is not part of the translation
* unit file or doesn't have a file-location.
* @see IASTNode#getFileLocation()
*/
public static int getNodeEndOffset(IASTNode node) {
if (!node.isPartOfTranslationUnitFile())
return -1;
IASTFileLocation nodeLocation = node.getFileLocation();
return nodeLocation != null ? nodeLocation.getNodeOffset() + nodeLocation.getNodeLength() : -1;
}
/**
* Returns the 1-based starting line number of the given node, or 0 if the node is not part of
* the translation unit file or doesn't have a file-location.
* @see IASTNode#getFileLocation()
*/
public static int getStartingLineNumber(IASTNode node) {
if (!node.isPartOfTranslationUnitFile())
return 0;
IASTFileLocation nodeLocation = node.getFileLocation();
return nodeLocation != null ? nodeLocation.getStartingLineNumber() : 0;
}
/**
* Returns the 1-based ending line number of the given node, or 0 if the node is not part of
* the translation unit file or doesn't have a file-location.
* @see IASTNode#getFileLocation()
*/
public static int getEndingLineNumber(IASTNode node) {
if (!node.isPartOfTranslationUnitFile())
return 0;
IASTFileLocation nodeLocation = node.getFileLocation();
return nodeLocation != null ? nodeLocation.getEndingLineNumber() : 0;
}
}

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* John Camelon (IBM) - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -22,13 +22,12 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/**
* Extern "C" construct.
*/
public class CPPASTLinkageSpecification extends ASTNode implements
ICPPASTLinkageSpecification, IASTAmbiguityParent {
public class CPPASTLinkageSpecification extends ASTNode
implements ICPPASTLinkageSpecification, IASTAmbiguityParent {
private String fLiteral;
private IASTDeclaration[] fAllDeclarations;
private IASTDeclaration[] fActiveDeclarations;
private int fLastDeclaration=-1;
private int fLastDeclaration = -1;
public CPPASTLinkageSpecification() {
}
@ -45,13 +44,10 @@ public class CPPASTLinkageSpecification extends ASTNode implements
@Override
public CPPASTLinkageSpecification copy(CopyStyle style) {
CPPASTLinkageSpecification copy = new CPPASTLinkageSpecification(fLiteral);
for (IASTDeclaration declaration : getDeclarations())
for (IASTDeclaration declaration : getDeclarations()) {
copy.addDeclaration(declaration == null ? null : declaration.copy(style));
copy.setOffsetAndLength(this);
if (style == CopyStyle.withLocations) {
copy.setCopyLocation(this);
}
return copy;
return copy(copy, style);
}
@Override
@ -70,7 +66,7 @@ public class CPPASTLinkageSpecification extends ASTNode implements
if (decl != null) {
decl.setParent(this);
decl.setPropertyInParent(OWNED_DECLARATION);
fAllDeclarations = ArrayUtil.appendAt( IASTDeclaration.class, fAllDeclarations, ++fLastDeclaration, decl);
fAllDeclarations = ArrayUtil.appendAt(IASTDeclaration.class, fAllDeclarations, ++fLastDeclaration, decl);
fActiveDeclarations= null;
}
}
@ -99,9 +95,9 @@ public class CPPASTLinkageSpecification extends ASTNode implements
public boolean accept(ASTVisitor action) {
if (action.shouldVisitDeclarations) {
switch (action.visit(this)) {
case ASTVisitor.PROCESS_ABORT : return false;
case ASTVisitor.PROCESS_SKIP : return true;
default : break;
case ASTVisitor.PROCESS_ABORT: return false;
case ASTVisitor.PROCESS_SKIP: return true;
default: break;
}
}

View file

@ -28,7 +28,6 @@ import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPFunction, ICPPComputableFunction {
private static final ICPPFunctionType FUNCTION_TYPE=
new CPPFunctionType(ProblemType.UNKNOWN_FOR_EXPRESSION, IType.EMPTY_TYPE_ARRAY);
private static final ICPPFunction[] NO_CANDIDATES= {};
/**
* Creates a CPPDeferredFunction given a set of overloaded functions
@ -52,7 +51,7 @@ public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPFuncti
* @return the constructed CPPDeferredFunction
*/
public static ICPPFunction createForName(char[] name) {
return new CPPDeferredFunction(null, name, NO_CANDIDATES);
return new CPPDeferredFunction(null, name, null);
}
private final IBinding fOwner;

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2009, 2012 Google, Inc and others.
* Copyright (c) 2009, 2013 Google, Inc 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
@ -177,9 +177,10 @@ public class AccessContext {
/**
* Returns access level to the members of a class.
*
* @param classType A class
* @param inheritedAccessLevel Access level inherited from derived class. One of: v_public, v_protected,
* v_private.
* @param inheritedAccessLevel Access level inherited from derived class.
* One of: v_public, v_protected, v_private.
* @return One of: v_public, v_protected, v_private.
*/
private int getMemberAccessLevel(ICPPClassType classType, int inheritedAccessLevel) {
@ -197,14 +198,14 @@ public class AccessContext {
return accessLevel;
}
private boolean isAccessibleBaseClass(ICPPClassType classType, ICPPClassType defived, int depth) {
private boolean isAccessibleBaseClass(ICPPClassType classType, ICPPClassType derived, int depth) {
if (depth > CPPSemantics.MAX_INHERITANCE_DEPTH)
return false;
if (defived.isSameType(classType))
if (derived.isSameType(classType))
return true;
ICPPBase[] bases = defived.getBases();
ICPPBase[] bases = ClassTypeHelper.getBases(derived, name);
if (bases != null) {
for (ICPPBase base : bases) {
IBinding baseClass = base.getBaseClass();

View file

@ -562,8 +562,12 @@ public class CPPSemantics {
return false;
}
private static void doKoenigLookup(LookupData data) throws DOMException {
public static void doKoenigLookup(LookupData data) throws DOMException {
data.ignoreUsingDirectives = true;
// Set 'qualified' to true for the duration of this function call
// so the calls to lookup() don't ascend into enclosing scopes.
boolean originalQualified = data.qualified;
data.qualified = true;
Set<ICPPFunction> friendFns = new HashSet<ICPPFunction>(2);
Set<ICPPNamespaceScope> associated = getAssociatedScopes(data, friendFns);
for (ICPPNamespaceScope scope : associated) {
@ -572,6 +576,7 @@ public class CPPSemantics {
}
}
mergeResults(data, friendFns.toArray(), false);
data.qualified = originalQualified;
}
static IBinding checkDeclSpecifier(IBinding binding, IASTName name, IASTNode decl) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Wind River Systems, Inc. and others.
* Copyright (c) 2012, 2013 Wind River Systems, Inc. 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
@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
import org.eclipse.cdt.internal.core.dom.parser.Value;
@ -46,21 +47,41 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
// the type of 'obj' (needed for correct overload resolution of 'member_function' later).
// Otherwise null.
private final IType fImpliedObjectType;
// Used to represent an EvalFunctionSet with zero functions.
// (We need the name in resolveFunction() - usually we get it from the CPPFunctionSet
// by asking the first function in the set for its name.)
// Exactly one of fFunctionSet and fName should be non-null.
private final char[] fName;
public EvalFunctionSet(CPPFunctionSet set, boolean addressOf, IType impliedObjectType, IASTNode pointOfDefinition) {
this(set, addressOf, impliedObjectType, findEnclosingTemplate(pointOfDefinition));
}
public EvalFunctionSet(CPPFunctionSet set, boolean addressOf, IType impliedObjectType, IBinding templateDefinition) {
super(templateDefinition);
fFunctionSet= set;
fAddressOf= addressOf;
fImpliedObjectType= impliedObjectType;
fName= null;
}
public EvalFunctionSet(char[] name, boolean addressOf, IASTNode pointOfDefinition) {
this(name, addressOf, findEnclosingTemplate(pointOfDefinition));
}
public EvalFunctionSet(char[] name, boolean addressOf, IBinding templateDefinition) {
super(templateDefinition);
fFunctionSet= null;
fAddressOf= addressOf;
fImpliedObjectType= null;
fName= name;
}
public CPPFunctionSet getFunctionSet() {
return fFunctionSet;
}
public boolean isAddressOf() {
return fAddressOf;
}
@ -81,6 +102,8 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
@Override
public boolean isTypeDependent() {
if (fFunctionSet == null)
return true;
final ICPPTemplateArgument[] args = fFunctionSet.getTemplateArguments();
if (args != null) {
for (ICPPTemplateArgument arg : args) {
@ -115,54 +138,74 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
return PRVALUE;
}
// Descriptive names for flags used during serialization.
private final static short FLAG_ADDRESS_OF = ITypeMarshalBuffer.FLAG1;
private final static short FLAG_HAS_FUNCTION_SET = ITypeMarshalBuffer.FLAG2;
private final static short FLAG_HAS_TEMPLATE_ARGS = ITypeMarshalBuffer.FLAG3;
@Override
public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException {
final ICPPFunction[] bindings = fFunctionSet.getBindings();
final ICPPTemplateArgument[] args = fFunctionSet.getTemplateArguments();
short firstBytes = ITypeMarshalBuffer.EVAL_FUNCTION_SET;
if (fAddressOf)
firstBytes |= ITypeMarshalBuffer.FLAG1;
if (args != null)
firstBytes |= ITypeMarshalBuffer.FLAG2;
firstBytes |= FLAG_ADDRESS_OF;
if (fFunctionSet != null) {
firstBytes |= FLAG_HAS_FUNCTION_SET;
final ICPPFunction[] bindings = fFunctionSet.getBindings();
final ICPPTemplateArgument[] args = fFunctionSet.getTemplateArguments();
if (args != null)
firstBytes |= FLAG_HAS_TEMPLATE_ARGS;
buffer.putShort(firstBytes);
buffer.putInt(bindings.length);
for (ICPPFunction binding : bindings) {
buffer.marshalBinding(binding);
}
if (args != null) {
buffer.putInt(args.length);
for (ICPPTemplateArgument arg : args) {
buffer.marshalTemplateArgument(arg);
buffer.putShort(firstBytes);
buffer.putInt(bindings.length);
for (ICPPFunction binding : bindings) {
buffer.marshalBinding(binding);
}
if (args != null) {
buffer.putInt(args.length);
for (ICPPTemplateArgument arg : args) {
buffer.marshalTemplateArgument(arg);
}
}
buffer.marshalType(fImpliedObjectType);
} else {
buffer.putShort(firstBytes);
buffer.putCharArray(fName);
}
buffer.marshalType(fImpliedObjectType);
marshalTemplateDefinition(buffer);
}
public static ISerializableEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException {
final boolean addressOf= (firstBytes & ITypeMarshalBuffer.FLAG1) != 0;
int bindingCount= buffer.getInt();
ICPPFunction[] bindings= new ICPPFunction[bindingCount];
for (int i = 0; i < bindings.length; i++) {
bindings[i]= (ICPPFunction) buffer.unmarshalBinding();
}
ICPPTemplateArgument[] args= null;
if ((firstBytes & ITypeMarshalBuffer.FLAG2) != 0) {
int len= buffer.getInt();
args = new ICPPTemplateArgument[len];
for (int i = 0; i < args.length; i++) {
args[i]= buffer.unmarshalTemplateArgument();
final boolean addressOf= (firstBytes & FLAG_ADDRESS_OF) != 0;
if ((firstBytes & FLAG_HAS_FUNCTION_SET) != 0) {
int bindingCount= buffer.getInt();
ICPPFunction[] bindings= new ICPPFunction[bindingCount];
for (int i = 0; i < bindings.length; i++) {
bindings[i]= (ICPPFunction) buffer.unmarshalBinding();
}
ICPPTemplateArgument[] args= null;
if ((firstBytes & FLAG_HAS_TEMPLATE_ARGS) != 0) {
int len= buffer.getInt();
args = new ICPPTemplateArgument[len];
for (int i = 0; i < args.length; i++) {
args[i]= buffer.unmarshalTemplateArgument();
}
}
IType impliedObjectType= buffer.unmarshalType();
IBinding templateDefinition= buffer.unmarshalBinding();
return new EvalFunctionSet(new CPPFunctionSet(bindings, args, null), addressOf, impliedObjectType, templateDefinition);
} else {
char[] name = buffer.getCharArray();
IBinding templateDefinition= buffer.unmarshalBinding();
return new EvalFunctionSet(name, addressOf, templateDefinition);
}
IType impliedObjectType= buffer.unmarshalType();
IBinding templateDefinition= buffer.unmarshalBinding();
return new EvalFunctionSet(new CPPFunctionSet(bindings, args, null), addressOf, impliedObjectType, templateDefinition);
}
@Override
public ICPPEvaluation instantiate(ICPPTemplateParameterMap tpMap, int packOffset,
ICPPClassSpecialization within, int maxdepth, IASTNode point) {
if (fFunctionSet == null)
return this;
ICPPTemplateArgument[] originalArguments = fFunctionSet.getTemplateArguments();
ICPPTemplateArgument[] arguments = originalArguments;
if (originalArguments != null)
@ -211,13 +254,42 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
* succeeded or not
*/
public ICPPEvaluation resolveFunction(ICPPEvaluation[] args, IASTNode point) {
ICPPFunction[] functions = fFunctionSet.getBindings();
LookupData data = new LookupData(functions[0].getNameCharArray(),
fFunctionSet.getTemplateArguments(), point);
// Set up the LookupData.
LookupData data;
ICPPFunction[] functions = null;
if (fFunctionSet == null) {
data = new LookupData(fName, null, point);
} else {
functions = fFunctionSet.getBindings();
data = new LookupData(functions[0].getNameCharArray(),
fFunctionSet.getTemplateArguments(), point);
data.foundItems = functions;
}
data.setFunctionArguments(false, args);
if (fImpliedObjectType != null)
data.setImpliedObjectType(fImpliedObjectType);
try {
// Perform ADL if appropriate.
if (fImpliedObjectType == null && !data.hasTypeOrMemberFunctionOrVariableResult()) {
CPPSemantics.doKoenigLookup(data);
Object[] foundItems = (Object[]) data.foundItems;
if (foundItems != null && (functions == null || foundItems.length > functions.length)) {
// ADL found additional functions.
functions = Arrays.copyOf(foundItems, foundItems.length, ICPPFunction[].class);
// doKoenigLookup() may introduce duplicates into the result. These must be
// eliminated to avoid resolveFunction() reporting an ambiguity. (Normally, when
// looukp() and doKoenigLookup() are called on the same LookupData object, the
// two functions coordinate using data stored in that object to eliminate
// duplicates, but in this case lookup() was called before with a different
// LookupData object and now we are only calling doKoenigLookup()).
functions = ArrayUtil.removeDuplicates(functions);
}
}
// Perform template instantiation and overload resolution.
IBinding binding = CPPSemantics.resolveFunction(data, functions, true);
if (binding instanceof ICPPFunction && !(binding instanceof ICPPUnknownBinding))
return new EvalBinding(binding, null, getTemplateDefinition());
@ -230,9 +302,11 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
@Override
public int determinePackSize(ICPPTemplateParameterMap tpMap) {
int r = CPPTemplates.PACK_SIZE_NOT_FOUND;
ICPPTemplateArgument[] templateArguments = fFunctionSet.getTemplateArguments();
for (ICPPTemplateArgument arg : templateArguments) {
r = CPPTemplates.combinePackSize(r, CPPTemplates.determinePackSize(arg, tpMap));
if (fFunctionSet != null) {
ICPPTemplateArgument[] templateArguments = fFunctionSet.getTemplateArguments();
for (ICPPTemplateArgument arg : templateArguments) {
r = CPPTemplates.combinePackSize(r, CPPTemplates.determinePackSize(arg, tpMap));
}
}
return r;
}

View file

@ -206,10 +206,13 @@ public class EvalID extends CPPDependentEvaluation {
}
if (binding instanceof CPPDeferredFunction) {
CPPDeferredFunction deferredFunction = (CPPDeferredFunction) binding;
if (deferredFunction.getCandidates() != null) {
CPPFunctionSet functionSet = new CPPFunctionSet(deferredFunction.getCandidates(), templateArgs, null);
ICPPFunction[] candidates = ((CPPDeferredFunction) binding).getCandidates();
if (candidates != null) {
CPPFunctionSet functionSet = new CPPFunctionSet(candidates, templateArgs, null);
return new EvalFunctionSet(functionSet, isAddressOf(expr), null, expr);
} else {
// Just store the name. ADL at the time of instantiation might come up with bindings.
return new EvalFunctionSet(name.getSimpleID(), isAddressOf(expr), expr);
}
}

View file

@ -472,12 +472,6 @@ public class LookupData extends ScopeLookupData {
public void setFunctionArguments(boolean containsImpliedObject, ICPPEvaluation... exprs) {
argsContainImpliedObject= containsImpliedObject;
functionArgs= exprs;
for (ICPPEvaluation e : exprs) {
if (e.isTypeDependent()) {
setIgnorePointOfDeclaration(true);
break;
}
}
}
public void setFunctionArguments(boolean containsImpliedObject, IASTInitializerClause... exprs) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
* Copyright (c) 2008, 2013 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@ -7,7 +7,8 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Institute for Software - initial API and implementation
* Institute for Software - initial API and implementation
* Sergey Prigogin (Google)
******************************************************************************/
package org.eclipse.cdt.internal.core.dom.rewrite.commenthandler;
@ -64,7 +65,7 @@ public class ASTCommenter {
}
private int checkOffsets(IASTNode node) {
int offset = ((ASTNode)node).getOffset();
int offset = ((ASTNode) node).getOffset();
int status = PROCESS_CONTINUE;
if (isCommentOnSameLine(node)
@ -82,8 +83,8 @@ public class ASTCommenter {
}
private boolean isCommentOnSameLine(IASTNode node) {
return commentNodeLocation.getStartingLineNumber() == node.getFileLocation()
.getEndingLineNumber();
return commentNodeLocation.getStartingLineNumber() ==
node.getFileLocation().getEndingLineNumber();
}
@Override
@ -168,41 +169,29 @@ public class ASTCommenter {
}
/**
* Creates a NodeCommentMap for the given TranslationUnit. This is the only way
* to get a NodeCommentMap which contains all the comments mapped against nodes.
* Creates a NodeCommentMap for the given AST. This is the only way to get a NodeCommentMap
* which contains all the comments mapped against nodes.
*
* @param tu TranslationUnit
* @param ast the AST
* @return NodeCommentMap
*/
public static NodeCommentMap getCommentedNodeMap(IASTTranslationUnit tu){
public static NodeCommentMap getCommentedNodeMap(IASTTranslationUnit ast) {
NodeCommentMap commentMap = new NodeCommentMap();
if (tu == null) {
if (ast == null) {
return commentMap;
}
IASTComment[] commentsArray = tu.getComments();
if (commentsArray == null) {
return commentMap;
}
// Note that constructing a real ArrayList is required here, since in filterNonTuComments, the
// remove-method will be invoked on the list's iterator. Calling it on the type Arrays$ArrayList (the
// resulting type of Arrays.asList() ) would throw a UnsupportedOperationException.
ArrayList<IASTComment> comments = new ArrayList<IASTComment>(Arrays.asList(commentsArray));
filterNonTuComments(comments);
return addCommentsToCommentMap(tu, comments);
}
/**
* Note that passing an ArrayList (instead of just List or Collection) is required here, since this
* guarantees that the call to the remove-method on the list's iterator will not result in an
* UnsupportedOperationException which might be the case for other Collection/List types.
*/
private static void filterNonTuComments(ArrayList<IASTComment> comments) {
Iterator<IASTComment> iterator = comments.iterator();
while (iterator.hasNext()) {
if (!iterator.next().isPartOfTranslationUnitFile()) {
iterator.remove();
IASTComment[] commentsArray = ast.getComments();
List<IASTComment> comments = new ArrayList<IASTComment>(commentsArray.length);
for (IASTComment comment : commentsArray) {
if (comment.isPartOfTranslationUnitFile()) {
comments.add(comment);
}
}
assignPreprocessorComments(commentMap, comments, ast);
CommentHandler commentHandler = new CommentHandler(comments);
ASTCommenterVisitor commenter = new ASTCommenterVisitor(commentHandler, commentMap);
ast.accept(commenter);
return commentMap;
}
private static boolean isCommentDirectlyBeforePreprocessorStatement(IASTComment comment,
@ -211,11 +200,11 @@ public class ASTCommenter {
return true;
}
IASTFileLocation commentLocation = comment.getFileLocation();
int preprcessorOffset = statement.getFileLocation().getNodeOffset();
if (preprcessorOffset > commentLocation.getNodeOffset()) {
PreprocessorRangeChecker vister = new PreprocessorRangeChecker(preprcessorOffset, commentLocation);
tu.accept(vister);
return vister.isPreStatementComment;
int preprocessorOffset = statement.getFileLocation().getNodeOffset();
if (preprocessorOffset > commentLocation.getNodeOffset()) {
PreprocessorRangeChecker visitor = new PreprocessorRangeChecker(preprocessorOffset, commentLocation);
tu.accept(visitor);
return visitor.isPreStatementComment;
}
return false;
}
@ -224,24 +213,12 @@ public class ASTCommenter {
return node.isPartOfTranslationUnitFile();
}
private static NodeCommentMap addCommentsToCommentMap(IASTTranslationUnit tu,
ArrayList<IASTComment> comments){
NodeCommentMap commentMap = new NodeCommentMap();
CommentHandler commHandler = new CommentHandler(comments);
assignPreprocessorComments(commentMap, comments, tu);
ASTCommenterVisitor commenter = new ASTCommenterVisitor(commHandler, commentMap);
tu.accept(commenter);
return commentMap;
}
/**
* Note that passing an ArrayList (instead of just List or Collection) is required here, since this
* guarantees that the call to the remove-method on the list's iterator will not result in an
* UnsupportedOperationException which might be the case for other Collection/List types.
* Puts leading and trailing comments to {@code commentMap} and removes them from
* the {@code comments} list.
*/
private static void assignPreprocessorComments(NodeCommentMap commentMap,
ArrayList<IASTComment> comments, IASTTranslationUnit tu) {
List<IASTComment> comments, IASTTranslationUnit tu) {
IASTPreprocessorStatement[] preprocessorStatementsArray = tu.getAllPreprocessorStatements();
if (preprocessorStatementsArray == null) {
return;
@ -252,6 +229,7 @@ public class ASTCommenter {
return;
}
List<IASTComment> freestandingComments = new ArrayList<IASTComment>(comments.size());
Iterator<IASTPreprocessorStatement> statementsIter = preprocessorStatements.iterator();
Iterator<IASTComment> commentIter = comments.iterator();
IASTPreprocessorStatement curStatement = getNextNodeInTu(statementsIter);
@ -261,18 +239,26 @@ public class ASTCommenter {
int commentLineNr = curComment.getFileLocation().getStartingLineNumber();
if (commentLineNr == statementLineNr) {
commentMap.addTrailingCommentToNode(curStatement, curComment);
commentIter.remove();
curComment = getNextNodeInTu(commentIter);
} else if (commentLineNr > statementLineNr) {
curStatement = getNextNodeInTu(statementsIter);
} else if (isCommentDirectlyBeforePreprocessorStatement(curComment, curStatement, tu)) {
commentMap.addLeadingCommentToNode(curStatement, curComment);
commentIter.remove();
curComment = getNextNodeInTu(commentIter);
} else {
freestandingComments.add(curComment);
curComment = getNextNodeInTu(commentIter);
}
}
while (curComment != null) {
freestandingComments.add(curComment);
curComment = getNextNodeInTu(commentIter);
}
if (freestandingComments.size() != comments.size()) {
comments.clear();
comments.addAll(freestandingComments);
}
}
private static <T extends IASTNode> T getNextNodeInTu(Iterator<T> iter) {

View file

@ -39,7 +39,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTCompositeTypeSpecifier
* @author Guido Zgraggen IFS
*/
public class ASTCommenterVisitor extends ASTVisitor {
protected CommentHandler commHandler;
protected CommentHandler commentHandler;
protected NodeCommentMap commentMap;
private NodeCommenter nodeCommenter;
@ -61,14 +61,14 @@ public class ASTCommenterVisitor extends ASTVisitor {
shouldVisitTranslationUnit = true;
}
public ASTCommenterVisitor(CommentHandler commHandler, NodeCommentMap commentMap) {
this.commHandler = commHandler;
public ASTCommenterVisitor(CommentHandler commentHandler, NodeCommentMap commentMap) {
this.commentHandler = commentHandler;
this.commentMap = commentMap;
init();
}
private void init() {
nodeCommenter = new NodeCommenter(this, commHandler, commentMap);
nodeCommenter = new NodeCommenter(this, commentHandler, commentMap);
}
@Override

View file

@ -62,13 +62,13 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTWhileStatement;
*/
public class NodeCommenter {
protected ASTVisitor visitor;
protected CommentHandler commHandler;
protected CommentHandler commentHandler;
protected NodeCommentMap commentMap;
protected List<IASTNode> children;
public NodeCommenter(ASTVisitor visitor, CommentHandler commHandler, NodeCommentMap commentMap) {
this.visitor = visitor;
this.commHandler = commHandler;
this.commentHandler = commHandler;
this.commentMap = commentMap;
this.children = new ArrayList<IASTNode>();
}
@ -122,17 +122,17 @@ public class NodeCommenter {
private void addLeadingCommentToMap(ASTNode node, IASTComment comment) {
commentMap.addLeadingCommentToNode(node, comment);
commHandler.allreadyAdded(comment);
commentHandler.allreadyAdded(comment);
}
private void addTrailingCommentToMap(ASTNode node, IASTComment comment) {
commentMap.addTrailingCommentToNode(node, comment);
commHandler.allreadyAdded(comment);
commentHandler.allreadyAdded(comment);
}
private void addFreestandingCommentToMap(ASTNode node, IASTComment comment) {
commentMap.addFreestandingCommentToNode(node, comment);
commHandler.allreadyAdded(comment);
commentHandler.allreadyAdded(comment);
}
private boolean isTrailing(ASTNode node, ASTNode com, int nodeLineNumber, int commentLineNumber) {
@ -200,8 +200,8 @@ public class NodeCommenter {
}
protected int appendComments(ASTNode node) {
while (commHandler.hasMore()) {
IASTComment comment = commHandler.getFirst();
while (commentHandler.hasMore()) {
IASTComment comment = commentHandler.getFirst();
if (isNotSameFile(node, comment)) {
return ASTVisitor.PROCESS_SKIP;
@ -215,8 +215,8 @@ public class NodeCommenter {
}
protected int appendFreestandingComments(ASTNode node) {
while (commHandler.hasMore()) {
IASTComment comment = commHandler.getFirst();
while (commentHandler.hasMore()) {
IASTComment comment = commentHandler.getFirst();
if (isNotSameFile(node, comment)) {
return ASTVisitor.PROCESS_SKIP;
@ -234,9 +234,9 @@ public class NodeCommenter {
}
public void appendRemainingComments(IASTDeclaration declaration) {
while (commHandler.hasMore()) {
IASTComment comment = commHandler.getFirst();
if (appendComment((ASTNode)declaration, comment)) {
while (commentHandler.hasMore()) {
IASTComment comment = commentHandler.getFirst();
if (appendComment((ASTNode) declaration, comment)) {
continue;
}
addFreestandingCommentToMap((ASTNode) declaration, comment);

View file

@ -330,15 +330,17 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
if (eval instanceof EvalFunctionSet) {
EvalFunctionSet e= (EvalFunctionSet) eval;
final CPPFunctionSet fset = e.getFunctionSet();
ICPPFunction[] a = fset.getBindings();
ICPPTemplateArgument[] b = fset.getTemplateArguments();
IType c = e.getImpliedObjectType();
ICPPFunction[] a2 = getCompositeFunctionArray(a);
ICPPTemplateArgument[] b2 = TemplateInstanceUtil.convert(this, b);
IType c2 = getCompositeType(c);
if (a != a2 || b != b2 || c != c2 || templateDefinition != templateDefinition2)
e= new EvalFunctionSet(new CPPFunctionSet(a2, b2, null), e.isAddressOf(), c2, templateDefinition2);
if (fset != null) {
ICPPFunction[] a = fset.getBindings();
ICPPTemplateArgument[] b = fset.getTemplateArguments();
IType c = e.getImpliedObjectType();
ICPPFunction[] a2 = getCompositeFunctionArray(a);
ICPPTemplateArgument[] b2 = TemplateInstanceUtil.convert(this, b);
IType c2 = getCompositeType(c);
if (a != a2 || b != b2 || c != c2 || templateDefinition != templateDefinition2)
e= new EvalFunctionSet(new CPPFunctionSet(a2, b2, null), e.isAddressOf(), c2, templateDefinition2);
}
return e;
}
if (eval instanceof EvalID) {

View file

@ -113,6 +113,7 @@ abstract class ASTPreprocessorNode extends ASTNode {
class ASTComment extends ASTPreprocessorNode implements IASTComment {
private final boolean fIsBlockComment;
private String fFilePath;
public ASTComment(IASTTranslationUnit parent, String filePath, int offset, int endOffset, boolean isBlockComment) {
super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, offset, endOffset);
fIsBlockComment= isBlockComment;

View file

@ -68,8 +68,8 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
/**
* C-Preprocessor providing tokens for the parsers. The class should not be used directly, rather than that
* you should be using the {@link IScanner} interface.
* C-Preprocessor providing tokens for the parsers. The class should not be used directly,
* rather than that you should be using the {@link IScanner} interface.
* @since 5.0
*/
public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
@ -87,8 +87,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
private static final char[] ONE = "1".toCharArray(); //$NON-NLS-1$
// standard built-ins
// Standard built-ins
private static final ObjectStyleMacro __CDT_PARSER__= new ObjectStyleMacro("__CDT_PARSER__".toCharArray(), ONE); //$NON-NLS-1$
private static final ObjectStyleMacro __cplusplus = new ObjectStyleMacro("__cplusplus".toCharArray(), ONE); //$NON-NLS-1$
private static final ObjectStyleMacro __STDC__ = new ObjectStyleMacro("__STDC__".toCharArray(), ONE); //$NON-NLS-1$
@ -374,7 +373,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return fLocationMap;
}
private void configureKeywords(ParserLanguage language, IScannerExtensionConfiguration configuration) {
private void configureKeywords(ParserLanguage language, IScannerExtensionConfiguration configuration) {
Keywords.addKeywordsPreprocessor(fPPKeywords);
if (language == ParserLanguage.C) {
Keywords.addKeywordsC(fKeywords);

View file

@ -6,9 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
import static org.eclipse.cdt.core.parser.OffsetLimitReachedException.ORIGIN_PREPROCESSOR_DIRECTIVE;
@ -39,7 +38,7 @@ public class IncludeGuardDetection {
Token t = l.nextToken();
if (t.getType() == IToken.tIDENTIFIER) {
char[] guard= null;
switch(ppKeywords.get(t.getCharImage())) {
switch (ppKeywords.get(t.getCharImage())) {
case IPreprocessorDirective.ppIfndef:
// #ifndef GUARD
t= l.nextToken();
@ -98,7 +97,7 @@ public class IncludeGuardDetection {
Token t= l.nextDirective();
if (t.getType() == IToken.tEND_OF_INPUT)
return true;
switch(ppKeywords.get(l.nextToken().getCharImage())) {
switch (ppKeywords.get(l.nextToken().getCharImage())) {
case IPreprocessorDirective.ppIf:
case IPreprocessorDirective.ppIfdef:
case IPreprocessorDirective.ppIfndef:
@ -124,7 +123,6 @@ public class IncludeGuardDetection {
return t;
}
public static boolean detectIncludeEndif(Lexer l) {
l.saveState();
try {

View file

@ -7,11 +7,16 @@
*
* Contributors:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
import java.io.File;
import org.eclipse.cdt.utils.PathUtil;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
/**
* Represents an entry of the include search path
*/
@ -42,14 +47,14 @@ public final class IncludeSearchPathElement {
public String getLocation(String includeDirective) {
if (fIsFrameworkDirectory) {
int firstSep = firstSeparator(includeDirective);
if (firstSep < 1) {
if (firstSep <= 0) {
return null;
}
String framework = includeDirective.substring(0, firstSep);
String file= includeDirective.substring(firstSep + 1);
if (file.length() == 0)
return null;
StringBuilder buf= new StringBuilder(fPath);
replace(buf, FRAMEWORK_VAR, framework);
replace(buf, FILE_VAR, file);
@ -58,6 +63,42 @@ public final class IncludeSearchPathElement {
return ScannerUtility.createReconciledPath(fPath, includeDirective);
}
/**
* Returns the include directive for the given location satisfying the condition
* {@code getLocation(getIncludeDirective(location) == location}. If no such include directive
* without ".." exists, returns {@code null}.
*/
public String getIncludeDirective(String location) {
IPath dirPath = new Path(fPath);
IPath locationPath = new Path(location);
if (fIsFrameworkDirectory) {
if (dirPath.segmentCount() != locationPath.segmentCount())
return null;
int i = PathUtil.matchingFirstSegments(dirPath, locationPath);
String dirSegment = dirPath.segment(i);
String locationSegment = locationPath.segment(i);
String framework = deduceVariable(FRAMEWORK_VAR, dirSegment, locationSegment);
if (framework == null)
return null;
i++;
dirPath = dirPath.removeFirstSegments(i);
locationPath = locationPath.removeFirstSegments(i);
i = PathUtil.matchingFirstSegments(dirPath, locationPath);
if (i < dirPath.segmentCount() - 1)
return null;
dirSegment = dirPath.segment(i);
locationSegment = locationPath.segment(i);
String file = deduceVariable(FILE_VAR, dirSegment, locationSegment);
if (file == null)
return null;
return framework + '/' + file;
}
if (!PathUtil.isPrefix(dirPath, locationPath))
return null;
return locationPath.removeFirstSegments(dirPath.segmentCount()).setDevice(null).toPortableString();
}
private int firstSeparator(String path) {
int firstSep= path.indexOf('/');
if (NON_SLASH_SEPARATOR) {
@ -73,6 +114,20 @@ public final class IncludeSearchPathElement {
}
}
private String deduceVariable(String varName, String raw, String substituted) {
int pos = raw.indexOf(varName);
if (pos < 0)
return null;
int suffixLength = raw.length() - pos - varName.length();
if (substituted.length() <= pos + suffixLength)
return null;
for (int i = 0; i < suffixLength; i++) {
if (raw.charAt(raw.length() - i) != substituted.charAt(substituted.length() - i))
return null;
}
return substituted.substring(pos, substituted.length() - suffixLength);
}
/**
* For debugging only.
*/

View file

@ -235,10 +235,11 @@ public class PDOM extends PlatformObject implements IPDOM {
* 141.0 - Storing enclosing template bindings for evaluations, bug 399829.
* 142.0 - Changed marshalling of evaluations to allow more than 15 evaluation kinds, bug 401479.
* 143.0 - Store implied object type in EvalFunctionSet, bug 402409.
* 144.0 - Add support for storing function sets with zero functions in EvalFunctionSet, bug 402498.
*/
private static final int MIN_SUPPORTED_VERSION= version(143, 0);
private static final int MAX_SUPPORTED_VERSION= version(143, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(143, 0);
private static final int MIN_SUPPORTED_VERSION= version(144, 0);
private static final int MAX_SUPPORTED_VERSION= version(144, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(144, 0);
private static int version(int major, int minor) {
return (major << 16) + minor;

View file

@ -1,37 +1,47 @@
/*******************************************************************************
* Copyright (c) 2005, 2007 Intel Corporation and others.
* Copyright (c) 2005, 2013 Intel 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:
* Intel Corporation - Initial API and implementation
* Intel Corporation - Initial API and implementation
* Andrew Gvozdev - Implementation of notification mechanism including changes to this API
*******************************************************************************/
package org.eclipse.cdt.internal.core.envvar;
import java.util.Collection;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.utils.envvar.IEnvironmentChangeEvent;
public class EnvironmentChangeEvent {
private static final IEnvironmentVariable[] EMPTY_VAR_ARRAY = new IEnvironmentVariable[0];
private IEnvironmentVariable[] fAddedVars, fRemovedVars, fChangedVars;
EnvironmentChangeEvent(IEnvironmentVariable[] addedVars, IEnvironmentVariable[] removedVars, IEnvironmentVariable[] changedVars){
fAddedVars = addedVars != null ? (IEnvironmentVariable[])addedVars.clone() : null;
fRemovedVars = removedVars != null ? (IEnvironmentVariable[])removedVars.clone() : null;
fChangedVars = changedVars != null ? (IEnvironmentVariable[])changedVars.clone() : null;
}
public IEnvironmentVariable[] getAddedVariables(){
return fAddedVars != null ? (IEnvironmentVariable[])fAddedVars.clone() : EMPTY_VAR_ARRAY;
/**
* Concrete implementation of event describing changes to environment variables defined by user
* on CDT Environment page in Preferences.
*/
public class EnvironmentChangeEvent implements IEnvironmentChangeEvent {
private IEnvironmentVariable[] oldVariables;
private IEnvironmentVariable[] newVariables;
/**
* Constructor.
*
* @param oldVars - set of environment variables before the change.
* @param newVars - set of environment variables after the change.
*/
public EnvironmentChangeEvent(Collection<IEnvironmentVariable> oldVars, Collection<IEnvironmentVariable> newVars) {
oldVariables = oldVars.toArray(new IEnvironmentVariable[oldVars.size()]);
newVariables = newVars.toArray(new IEnvironmentVariable[newVars.size()]);
}
public IEnvironmentVariable[] getRemovedVariables(){
return fRemovedVars != null ? (IEnvironmentVariable[])fRemovedVars.clone() : EMPTY_VAR_ARRAY;
@Override
public IEnvironmentVariable[] getOldVariables() {
return oldVariables;
}
public IEnvironmentVariable[] getChangedVariables(){
return fChangedVars != null ? (IEnvironmentVariable[])fChangedVars.clone() : EMPTY_VAR_ARRAY;
@Override
public IEnvironmentVariable[] getNewVariables() {
return newVariables;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2011 Intel Corporation and others.
* Copyright (c) 2005, 2013 Intel 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
@ -9,23 +9,23 @@
* Intel Corporation - Initial API and implementation
* James Blackburn (Broadcom Corp.)
* IBM Corporation
* Andrew Gvozdev - Notification mechanism for changes to environment variables
*******************************************************************************/
package org.eclipse.cdt.internal.core.envvar;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.internal.core.settings.model.CConfigurationSpecSettings;
import org.eclipse.cdt.internal.core.settings.model.IInternalCCfgInfo;
import org.eclipse.cdt.utils.envvar.EnvVarOperationProcessor;
import org.eclipse.cdt.utils.envvar.IEnvironmentChangeListener;
import org.eclipse.cdt.utils.envvar.PrefsStorableEnvironment;
import org.eclipse.cdt.utils.envvar.StorableEnvironment;
import org.eclipse.cdt.utils.envvar.StorableEnvironmentLoader;
import org.eclipse.core.resources.IProject;
@ -52,114 +52,26 @@ import org.osgi.service.prefs.Preferences;
*
* @since 3.0
*/
public class UserDefinedEnvironmentSupplier extends
StorableEnvironmentLoader
implements ICoreEnvironmentVariableSupplier{
public class UserDefinedEnvironmentSupplier extends StorableEnvironmentLoader implements ICoreEnvironmentVariableSupplier {
public static final String NODENAME = "environment"; //$NON-NLS-1$
public static final String PREFNAME_WORKSPACE = "workspace"; //$NON-NLS-1$
public static final String PREFNAME_PROJECT = "project"; //$NON-NLS-1$
public static final String NODENAME_CFG = "project"; //$NON-NLS-1$
/* private static final String fNonOverloadableVariables[] = new String[]{
//users not allowed currently to override the "CWD" and "PWD" variables
EnvVarOperationProcessor.normalizeName("CWD"), //$NON-NLS-1$
EnvVarOperationProcessor.normalizeName("PWD") //$NON-NLS-1$
};
*/
private StorableEnvironment fWorkspaceVariables;
private PrefsStorableEnvironment fWorkspaceVariables;
private StorableEnvironment fOverrideVariables = new StorableEnvironment(false);
static class VarKey {
private IEnvironmentVariable fVar;
private boolean fNameOnly;
private int fCode;
VarKey(IEnvironmentVariable var, boolean nameOnly) {
fVar = var;
fNameOnly = nameOnly;
}
public IEnvironmentVariable getVariable() {
return fVar;
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof VarKey))
return false;
VarKey other = (VarKey)obj;
IEnvironmentVariable otherVar = other.fVar;
if (fVar == otherVar)
return true;
if (!CDataUtil.objectsEqual(fVar.getName(), otherVar.getName()))
return false;
if (fNameOnly)
return true;
if (fVar.getOperation() != otherVar.getOperation())
return false;
if (!CDataUtil.objectsEqual(fVar.getValue(), otherVar.getValue()))
return false;
if (!CDataUtil.objectsEqual(fVar.getDelimiter(),otherVar.getDelimiter()))
return false;
return true;
}
@Override
public int hashCode() {
int code = fCode;
if (code == 0) {
code = 47;
String tmp = fVar.getName();
if (tmp != null)
code += tmp.hashCode();
if (fNameOnly)
return code;
code += fVar.getOperation();
tmp = fVar.getValue();
if (tmp != null)
code += tmp.hashCode();
tmp = fVar.getDelimiter();
if (tmp != null)
code += tmp.hashCode();
fCode = code;
}
return code;
}
}
public StorableEnvironment getEnvironment(Object context) {
return getEnvironment(context,true);
return getEnvironment(context, false);
}
protected StorableEnvironment getEnvironment(Object context, boolean forceLoad) {
// if (context == null)
// return null;
StorableEnvironment env = null;
if (context instanceof IInternalCCfgInfo) {
try {
CConfigurationSpecSettings settings = ((IInternalCCfgInfo)context).getSpecSettings();
env = settings.getEnvironment();
if (env == null && forceLoad) {
if (env == null || forceLoad) {
env = loadEnvironment(context, settings.isReadOnly());
settings.setEnvironment(env);
}
@ -168,8 +80,8 @@ public class UserDefinedEnvironmentSupplier extends
}
}
else if (context instanceof IWorkspace || context == null) {
if (fWorkspaceVariables == null && forceLoad)
fWorkspaceVariables = loadEnvironment(context, false);
if (fWorkspaceVariables == null || forceLoad)
fWorkspaceVariables = (PrefsStorableEnvironment) loadEnvironment(context, false);
env = fWorkspaceVariables;
}
@ -238,7 +150,7 @@ public class UserDefinedEnvironmentSupplier extends
}
private Preferences getWorkspaceNode() {
Preferences prefNode = new InstanceScope().getNode(CCorePlugin.PLUGIN_ID);
Preferences prefNode = InstanceScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID);
if (prefNode == null)
return null;
@ -291,81 +203,11 @@ public class UserDefinedEnvironmentSupplier extends
fWorkspaceVariables.setAppendEnvironment(env.appendEnvironment());
fWorkspaceVariables.setAppendContributedEnvironment(env.appendContributedEnvironment());
EnvironmentChangeEvent event = createEnvironmentChangeEvent(newVariables, oldVariables);
storeWorkspaceEnvironment(true);
// updateProjectInfo(null);
return event != null;
return ! Arrays.equals(oldVariables, newVariables);
}
static EnvironmentChangeEvent createEnvironmentChangeEvent(IEnvironmentVariable[] newVars, IEnvironmentVariable[] oldVars) {
IEnvironmentVariable[] addedVars = null, removedVars = null, changedVars = null;
if (oldVars == null || oldVars.length == 0) {
if (newVars != null && newVars.length != 0)
addedVars = newVars.clone();
} else if (newVars == null || newVars.length == 0) {
removedVars = oldVars.clone();
} else {
HashSet<VarKey> newSet = new HashSet<VarKey>(newVars.length);
HashSet<VarKey> oldSet = new HashSet<VarKey>(oldVars.length);
for (IEnvironmentVariable newVar : newVars) {
newSet.add(new VarKey(newVar, true));
}
for (IEnvironmentVariable oldVar : oldVars) {
oldSet.add(new VarKey(oldVar, true));
}
@SuppressWarnings("unchecked")
HashSet<VarKey> newSetCopy = (HashSet<VarKey>)newSet.clone();
newSet.removeAll(oldSet);
oldSet.removeAll(newSetCopy);
if (newSet.size() != 0) {
addedVars = varsFromKeySet(newSet);
}
if (oldSet.size() != 0) {
removedVars = varsFromKeySet(oldSet);
}
newSetCopy.removeAll(newSet);
HashSet<VarKey> modifiedSet = new HashSet<VarKey>(newSetCopy.size());
for (VarKey key : newSetCopy) {
modifiedSet.add(new VarKey(key.getVariable(), false));
}
for (IEnvironmentVariable oldVar : oldVars) {
modifiedSet.remove(new VarKey(oldVar, false));
}
if (modifiedSet.size() != 0)
changedVars = varsFromKeySet(modifiedSet);
}
if (addedVars != null || removedVars != null || changedVars != null)
return new EnvironmentChangeEvent(addedVars, removedVars, changedVars);
return null;
}
static IEnvironmentVariable[] varsFromKeySet(Set<VarKey> set) {
IEnvironmentVariable vars[] = new IEnvironmentVariable[set.size()];
int i = 0;
for(Iterator<VarKey> iter = set.iterator(); iter.hasNext(); i++) {
VarKey key = iter.next();
vars[i] = key.getVariable();
}
return vars;
}
public void storeProjectEnvironment(ICProjectDescription des, boolean force) {
ICConfigurationDescription cfgs[] = des.getConfigurations();
for (ICConfigurationDescription cfg : cfgs) {
@ -448,7 +290,6 @@ public class UserDefinedEnvironmentSupplier extends
return null;
IEnvironmentVariable var = env.createVariable(name,value,op,delimiter);
if (env.isChanged()) {
// updateProjectInfo(context);
env.setChanged(false);
}
return var;
@ -459,9 +300,6 @@ public class UserDefinedEnvironmentSupplier extends
if (env == null)
return null;
IEnvironmentVariable var = env.deleteVariable(name);
if (var != null) {
// updateProjectInfo(context);
}
return var;
}
@ -470,9 +308,7 @@ public class UserDefinedEnvironmentSupplier extends
if (env == null)
return;
if (env.deleteAll()) {
// updateProjectInfo(context);
}
env.deleteAll();
}
public void setVariables(IEnvironmentVariable vars[], Object context) {
@ -482,28 +318,14 @@ public class UserDefinedEnvironmentSupplier extends
env.setVariales(vars);
if (env.isChanged()) {
// updateProjectInfo(context);
env.setChanged(false);
}
}
// protected void updateProjectInfo(Object context) {
// }
// protected void cfgVarsModified(ICConfigurationDescription cfg) {
// cfg.setRebuildState(true);
// EnvironmentVariableProvider.getDefault().checkBuildPathVariables(cfg);
// }
protected String getValidName(String name) {
if (name == null || (name = name.trim()).length() == 0)
return null;
// if (fNonOverloadableVariables != null) {
// for(int i = 0; i < fNonOverloadableVariables.length; i++) {
// if (fNonOverloadableVariables[i].equals(EnvVarOperationProcessor.normalizeName(name)))
// return null;
// }
// }
return name;
}
@ -548,4 +370,30 @@ public class UserDefinedEnvironmentSupplier extends
}
}
/**
* Adds a listener that will be notified of changes in environment variables.
*
* @param listener - the listener to add
* @since 5.5
*/
public void registerEnvironmentChangeListener(IEnvironmentChangeListener listener) {
if (fWorkspaceVariables == null) {
getEnvironment(null, false);
}
if (fWorkspaceVariables != null) {
fWorkspaceVariables.registerEnvironmentChangeListener(listener);
}
}
/**
* Removes an environment variables change listener.
*
* @param listener - the listener to remove.
* @since 5.5
*/
public void unregisterEnvironmentChangeListener(IEnvironmentChangeListener listener) {
if (fWorkspaceVariables != null) {
fWorkspaceVariables.unregisterEnvironmentChangeListener(listener);
}
}
}

View file

@ -464,8 +464,8 @@ public class Scribe {
printIndentationIfNecessary(buffer);
buffer.append(lineSeparator);
}
lastNumberOfNewLines+= linesNumber;
line+= linesNumber;
lastNumberOfNewLines += linesNumber;
line += linesNumber;
column= 1;
needSpace= false;
pendingSpace= false;
@ -475,8 +475,8 @@ public class Scribe {
printIndentationIfNecessary(buffer);
buffer.append(lineSeparator);
}
lastNumberOfNewLines+= linesNumber;
line+= linesNumber;
lastNumberOfNewLines += linesNumber;
line += linesNumber;
column= 1;
needSpace= false;
pendingSpace= false;
@ -491,8 +491,8 @@ public class Scribe {
printIndentationIfNecessary(buffer);
buffer.append(lineSeparator);
}
lastNumberOfNewLines+= realNewLineNumber;
line+= realNewLineNumber;
lastNumberOfNewLines += realNewLineNumber;
line += realNewLineNumber;
column= 1;
needSpace= false;
pendingSpace= false;
@ -771,14 +771,8 @@ public class Scribe {
printComment();
currentPosition= scanner.getCurrentPosition();
}
if (pendingSpace) {
addInsertEdit(currentPosition, SPACE);
pendingSpace= false;
needSpace= false;
}
if (startOffset + length < currentPosition) {
// don't move backwards
return;
return; // Don't move backwards
}
boolean savedPreserveNL= preserveNewLines;
boolean savedSkipOverInactive= skipOverInactive;
@ -994,7 +988,7 @@ public class Scribe {
addReplaceEdit(start, previousStart - 1, String.valueOf(buffer));
} else {
column+= (nextCharacterStart - previousStart);
column += (nextCharacterStart - previousStart);
}
isNewLine= false;
}
@ -1041,7 +1035,7 @@ public class Scribe {
column= 1;
line++;
} else {
column+= (nextCharacterStart - previousStart);
column += (nextCharacterStart - previousStart);
}
isNewLine= false;
}
@ -1513,7 +1507,7 @@ public class Scribe {
while (column <= indentationLevel - indentationLevel % tabLength) {
buffer.append('\t');
int complement= tabLength - ((column - 1) % tabLength); // amount of space
column+= complement;
column += complement;
needSpace= false;
}
while (column <= indentationLevel) {
@ -1540,7 +1534,7 @@ public class Scribe {
if (column <= columnForLeadingIndents) {
if ((column - 1 + tabLength) <= indentationLevel) {
buffer.append('\t');
column+= tabLength;
column += tabLength;
} else if ((column - 1 + indentationSize) <= indentationLevel) {
// print one indentation
for (int i= 0, max= indentationSize; i < max; i++) {
@ -1563,7 +1557,7 @@ public class Scribe {
while (column <= indentationLevel) {
if ((column - 1 + tabLength) <= indentationLevel) {
buffer.append('\t');
column+= tabLength;
column += tabLength;
} else if ((column - 1 + indentationSize) <= indentationLevel) {
// print one indentation
for (int i= 0, max= indentationSize; i < max; i++) {

View file

@ -0,0 +1,244 @@
/*******************************************************************************
* Copyright (c) 2012, 2013 Andrew Gvozdev 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:
* Andrew Gvozdev - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.utils.PathUtil;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
/**
* A collection of MinGW-related utility methods.
*/
public class MinGW {
public static final String ENV_MINGW_HOME = "MINGW_HOME"; //$NON-NLS-1$
public static final String ENV_MSYS_HOME = "MSYS_HOME"; //$NON-NLS-1$
private static final String ENV_PATH = "PATH"; //$NON-NLS-1$
private static final boolean isWindowsPlatform = Platform.getOS().equals(Platform.OS_WIN32);
private static String envPathValueCached = null;
private static String envMinGWHomeValueCached = null;
private static String minGWLocation = null;
private static boolean isMinGWLocationCached = false;
private static String envMinGWHomeValueCached_msys = null;
private static String mSysLocation = null;
private static boolean isMSysLocationCached = false;
private final static Map<String/*envPath*/, String/*mingwLocation*/> mingwLocationCache = Collections.synchronizedMap(new WeakHashMap<String, String>(1));
/**
* @return The absolute path to MinGW root folder or {@code null} if not found
*/
private static String findMinGWRoot(String envPathValue, String envMinGWHomeValue) {
String rootValue = null;
// Check $MINGW_HOME
if (envMinGWHomeValue != null && !envMinGWHomeValue.isEmpty()) {
IPath mingwBinDir = new Path(envMinGWHomeValue + "\\bin"); //$NON-NLS-1$
if (mingwBinDir.toFile().isDirectory()) {
rootValue = mingwBinDir.removeLastSegments(1).toOSString();
}
}
// Try the mingw directory in the platform install directory
// CDT distributions like Wascana may distribute MinGW like that
if (rootValue == null) {
IPath installPath = new Path(Platform.getInstallLocation().getURL().getFile());
IPath mingwBinDir = installPath.append("mingw\\bin"); //$NON-NLS-1$
if (mingwBinDir.toFile().isDirectory()) {
rootValue = mingwBinDir.removeLastSegments(1).toOSString();
}
}
// Look in PATH values. Look for mingw32-gcc.exe or x86_64-w64-mingw32-gcc.exe
if (rootValue == null) {
rootValue = findMingwInPath(envPathValue);
}
// Try the default MinGW install dir
if (rootValue == null) {
IPath mingwBinDir = new Path("C:\\MinGW"); //$NON-NLS-1$
if (mingwBinDir.toFile().isDirectory()) {
rootValue = mingwBinDir.toOSString();
}
}
return rootValue;
}
private static String findMingwInPath(String envPath) {
if (envPath == null) {
// $PATH from user preferences
IEnvironmentVariable varPath = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(ENV_PATH, null, true);
if (varPath != null) {
envPath = varPath.getValue();
}
}
String mingwLocation = mingwLocationCache.get(envPath);
// check if WeakHashMap contains the key as null may be the cached value
if (mingwLocation == null && !mingwLocationCache.containsKey(envPath)) {
// Check for MinGW-w64 on Windows 64 bit, see http://mingw-w64.sourceforge.net/
if (Platform.ARCH_X86_64.equals(Platform.getOSArch())) {
IPath gcc64Loc = PathUtil.findProgramLocation("x86_64-w64-mingw32-gcc.exe", envPath); //$NON-NLS-1$
if (gcc64Loc != null) {
mingwLocation = gcc64Loc.removeLastSegments(2).toOSString();
}
}
// Look for mingw32-gcc.exe
if (mingwLocation == null) {
IPath gccLoc = PathUtil.findProgramLocation("mingw32-gcc.exe", envPath); //$NON-NLS-1$
if (gccLoc != null) {
mingwLocation = gccLoc.removeLastSegments(2).toOSString();
}
}
mingwLocationCache.put(envPath, mingwLocation);
}
return mingwLocation;
}
private static String findMSysRoot(String envMinGWHomeValue) {
String msysHome = null;
// Look in the install location parent dir
IPath installPath = new Path(Platform.getInstallLocation().getURL().getFile());
IPath installMsysBin = installPath.append("msys\\bin"); //$NON-NLS-1$
if (installMsysBin.toFile().isDirectory()) {
msysHome = installMsysBin.removeLastSegments(1).toOSString();
}
// Look under $MINGW_HOME
if (msysHome == null) {
if (envMinGWHomeValue != null && !envMinGWHomeValue.isEmpty()) {
IPath minGwMsysBin = new Path(envMinGWHomeValue + "\\msys\\1.0\\bin"); //$NON-NLS-1$
if (minGwMsysBin.toFile().isDirectory()) {
msysHome = minGwMsysBin.removeLastSegments(1).toOSString();
}
}
}
// Try under default MinGW dir
if (msysHome == null) {
IPath minGwMsysBin = new Path("C:\\MinGW\\msys\\1.0\\bin"); //$NON-NLS-1$
if (minGwMsysBin.toFile().isDirectory()) {
msysHome = minGwMsysBin.removeLastSegments(1).toOSString();
}
}
// Try in default MSYS root folder
if (msysHome == null) {
IPath defaultMsysBin = new Path("C:\\msys\\1.0\\bin"); //$NON-NLS-1$
if (defaultMsysBin.toFile().isDirectory()) {
msysHome = defaultMsysBin.removeLastSegments(1).toOSString();
}
}
return msysHome;
}
/**
* Find location where MinGW is installed. A number of locations is being checked,
* such as environment variable $MINGW_HOME, $PATH, Windows registry et al.
* <br><br>
* If you use this do not cache results to ensure user preferences are accounted for.
* Please rely on internal caching.
*
* @return MinGW root ("/") path in Windows format.
*/
public static String getMinGWHome() {
if (!isWindowsPlatform) {
return null;
}
IEnvironmentVariable varPath = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(ENV_PATH, null, true);
String envPathValue = varPath != null ? varPath.getValue() : null;
IEnvironmentVariable varMinGWHome = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(ENV_MINGW_HOME, null, true);
String envMinGWHomeValue = varMinGWHome != null ? varMinGWHome.getValue() : null;
// isMinGWLocationCached is used to figure fact of caching when all cached objects are null
if (isMinGWLocationCached && CDataUtil.objectsEqual(envPathValue, envPathValueCached) && CDataUtil.objectsEqual(envMinGWHomeValue, envMinGWHomeValueCached)) {
return minGWLocation;
}
minGWLocation = findMinGWRoot(envPathValue, envMinGWHomeValue);
envPathValueCached = envPathValue;
envMinGWHomeValueCached = envMinGWHomeValue;
isMinGWLocationCached = true;
return minGWLocation;
}
/**
* Find location where MSys is installed. Environment variable $MSYS_HOME and
* some predetermined locations are being checked.
* <br><br>
* If you use this do not cache results to ensure user preferences are accounted for.
* Please rely on internal caching.
*
* @return MSys root ("/") path in Windows format.
*/
public static String getMSysHome() {
if (!isWindowsPlatform) {
return null;
}
// Use $MSYS_HOME if defined
IEnvironmentVariable varMsysHome = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(ENV_MSYS_HOME, null, true);
String msysHomeValue = varMsysHome != null ? varMsysHome.getValue() : null;
if (msysHomeValue != null) {
return msysHomeValue;
}
String envMinGWHomeValue = getMinGWHome();
// isMSysLocationCached is used to figure whether it was cached when all cached objects are null
if (isMSysLocationCached && CDataUtil.objectsEqual(envMinGWHomeValue, envMinGWHomeValueCached_msys)) {
return mSysLocation;
}
mSysLocation = findMSysRoot(envMinGWHomeValue);
envMinGWHomeValueCached_msys = envMinGWHomeValue;
isMSysLocationCached = true;
return mSysLocation;
}
/**
* Check if MinGW is available in the path.
*
* @param envPath - list of directories to search for MinGW separated
* by path separator (format of environment variable $PATH)
* or {@code null} to use current $PATH.
* @return {@code true} if MinGW is available, {@code false} otherwise.
*/
public static boolean isAvailable(String envPath) {
return isWindowsPlatform && findMingwInPath(envPath) != null;
}
/**
* Check if MinGW is available in $PATH.
*
* @return {@code true} if MinGW is available, {@code false} otherwise.
*/
public static boolean isAvailable() {
return isWindowsPlatform && findMingwInPath(null) != null;
}
}

View file

@ -0,0 +1,34 @@
/*******************************************************************************
* Copyright (c) 2013, 2013 Andrew Gvozdev 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:
* Andrew Gvozdev - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.utils.envvar;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
/**
* A class to describe changes to environment variables defined by user
* on CDT Environment page in Preferences.
*
* @since 5.5
*/
public interface IEnvironmentChangeEvent {
/**
* @return an array of environment variables before the changes. If there are no variables,
* returns an empty array.
*/
public IEnvironmentVariable[] getOldVariables();
/**
* @return an array of environment variables after the changes. If there are no variables,
* returns an empty array.
*/
public IEnvironmentVariable[] getNewVariables();
}

View file

@ -0,0 +1,27 @@
/*******************************************************************************
* Copyright (c) 2013, 2013 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.utils.envvar;
/**
* Interface for listeners to changes in environment variables defined by user
* on CDT Environment page in Preferences.
*
* @since 5.5
*/
public interface IEnvironmentChangeListener {
/**
* Indicates that environment variables have been changed.
*
* @param event - details of the event.
*/
public void handleEvent(IEnvironmentChangeEvent event);
}

View file

@ -22,7 +22,9 @@ import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.envvar.EnvironmentChangeEvent;
import org.eclipse.cdt.utils.envvar.StorableEnvironmentLoader.ISerializeInfo;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.INodeChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
@ -72,6 +74,8 @@ public class PrefsStorableEnvironment extends StorableEnvironment {
private boolean fAppendChanged = false;
private boolean fAppendContributedChanged = false;
private static ListenerList fEnvironmentChangeListeners = new ListenerList(ListenerList.IDENTITY);
/** A listener for changes in the backing store */
private static class PrefListener implements IPreferenceChangeListener, INodeChangeListener {
@ -401,6 +405,9 @@ public class PrefsStorableEnvironment extends StorableEnvironment {
void serialize() {
if (!isDirty())
return;
HashMap<String, IEnvironmentVariable> oldEnv = new HashMap<String, IEnvironmentVariable>(fCachedSerialEnv);
Preferences element = fSerialEnv.getNode().node(fSerialEnv.getPrefName());
element.putBoolean(ATTRIBUTE_APPEND, fAppend);
fAppendChanged = false;
@ -430,6 +437,11 @@ public class PrefsStorableEnvironment extends StorableEnvironment {
} catch (BackingStoreException e) {
CCorePlugin.log(e);
}
if (fAppendChanged || fAppendContributedChanged || !oldEnv.equals(fCachedSerialEnv)) {
IEnvironmentChangeEvent event = new EnvironmentChangeEvent(oldEnv.values(), fCachedSerialEnv.values());
notifyLanguageSettingsChangeListeners(event);
}
}
@Override
@ -535,6 +547,37 @@ public class PrefsStorableEnvironment extends StorableEnvironment {
(fDeletedVariables != null && !fDeletedVariables.isEmpty());
}
/**
* Adds a listener that will be notified of changes in environment variables.
*
* @param listener - the listener to add
* @since 5.5
*/
public void registerEnvironmentChangeListener(IEnvironmentChangeListener listener) {
fEnvironmentChangeListeners.add(listener);
}
/**
* Removes an environment variables change listener.
*
* @param listener - the listener to remove.
* @since 5.5
*/
public void unregisterEnvironmentChangeListener(IEnvironmentChangeListener listener) {
fEnvironmentChangeListeners.remove(listener);
}
/**
* Notifies all environment change listeners of a change in environment.
*
* @param event - the {@link IEnvironmentChangeEvent} event to be broadcast.
*/
private static void notifyLanguageSettingsChangeListeners(IEnvironmentChangeEvent event) {
for (Object listener : fEnvironmentChangeListeners.getListeners()) {
((IEnvironmentChangeListener) listener).handleEvent(event);
}
}
@Override
protected void finalize() throws Throwable {
super.finalize();

View file

@ -24,13 +24,15 @@ const SimpleStruct simpleStruct = { 1, "mySimple", 0.1232 };
\
}
const SimpleStruct array[] = { { SIZEOF( simpleStruct, num ),
const SimpleStruct array[] = { {
SIZEOF( simpleStruct, num ),
#if FOO
"foo"
# else
"bar"
#endif
, 0.5 }, { SIZEOF( simpleStruct, floatNum ), "name", 1.1 } };
, 0.5 }, {
SIZEOF( simpleStruct, floatNum ), "name", 1.1 } };
// single line outside scope

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* Copyright (c) 2012, 2013 Google, Inc 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
@ -22,7 +22,6 @@ import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.TextSelection;
@ -56,8 +55,6 @@ import org.eclipse.cdt.internal.ui.refactoring.CRefactoringContext;
* Common base for refactoring tests.
*/
public abstract class RefactoringTestBase extends BaseTestCase {
protected static final NullProgressMonitor NULL_PROGRESS_MONITOR = new NullProgressMonitor();
/** Allows empty files to be created during test setup. */
protected boolean createEmptyFiles = true;
/** See {@link PreferenceConstants.CLASS_MEMBER_ASCENDING_VISIBILITY_ORDER} */
@ -137,7 +134,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
public void tearDown() throws Exception {
if (cproject != null) {
cproject.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT,
NULL_PROGRESS_MONITOR);
npm());
}
resetPreferences();
super.tearDown();
@ -175,7 +172,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
protected void executeRefactoring(Refactoring refactoring, RefactoringContext context,
boolean withUserInput, boolean expectedSuccess) throws CoreException, Exception {
try {
RefactoringStatus initialStatus = refactoring.checkInitialConditions(NULL_PROGRESS_MONITOR);
RefactoringStatus initialStatus = refactoring.checkInitialConditions(npm());
if (!expectedSuccess) {
assertStatusFatalError(initialStatus);
return;
@ -190,7 +187,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
if (withUserInput)
simulateUserInput();
RefactoringStatus finalStatus = refactoring.checkFinalConditions(NULL_PROGRESS_MONITOR);
RefactoringStatus finalStatus = refactoring.checkFinalConditions(npm());
if (expectedFinalWarnings != 0) {
assertStatusWarning(finalStatus, expectedFinalWarnings);
} else if (expectedFinalInfos != 0) {
@ -198,8 +195,8 @@ public abstract class RefactoringTestBase extends BaseTestCase {
} else {
assertStatusOk(finalStatus);
}
Change change = refactoring.createChange(NULL_PROGRESS_MONITOR);
change.perform(NULL_PROGRESS_MONITOR);
Change change = refactoring.createChange(npm());
change.perform(npm());
} finally {
if (context != null)
context.dispose();
@ -212,7 +209,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
RefactoringHistory history = RefactoringHistoryService.getInstance().readRefactoringHistory(
new ByteArrayInputStream(scriptSource.getBytes()), 0);
for (RefactoringDescriptorProxy proxy : history.getDescriptors()) {
RefactoringDescriptor descriptor = proxy.requestDescriptor(NULL_PROGRESS_MONITOR);
RefactoringDescriptor descriptor = proxy.requestDescriptor(npm());
RefactoringStatus status = new RefactoringStatus();
RefactoringContext context = descriptor.createRefactoringContext(status);
assertTrue(status.isOK());

View file

@ -22,6 +22,7 @@ import org.eclipse.cdt.ui.tests.refactoring.extractlocalvariable.ExtractLocalVar
import org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest;
import org.eclipse.cdt.ui.tests.refactoring.hidemethod.HideMethodRefactoringTest;
import org.eclipse.cdt.ui.tests.refactoring.implementmethod.ImplementMethodRefactoringTest;
import org.eclipse.cdt.ui.tests.refactoring.includes.IncludesTestSuite;
import org.eclipse.cdt.ui.tests.refactoring.rename.RenameRegressionTests;
import org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest;
import org.eclipse.cdt.ui.tests.refactoring.utils.UtilTestSuite;
@ -42,6 +43,7 @@ public class RefactoringTestSuite extends TestSuite {
suite.addTest(ImplementMethodRefactoringTest.suite());
suite.addTest(ExtractLocalVariableRefactoringTest.suite());
suite.addTest(ToggleRefactoringTest.suite());
suite.addTest(IncludesTestSuite.suite());
return suite;
}
}

View file

@ -1,11 +1,11 @@
/*******************************************************************************
* Rapperswil, University of applied sciences 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:
* 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:
* Institute for Software - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
@ -181,7 +181,6 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase {
assertRefactoringSuccess();
}
//A.h
//#ifndef A_H_
//#define A_H_
@ -308,7 +307,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase {
public void testLocalVariableDeclaration_3() throws Exception {
assertRefactoringSuccess();
}
//A.h
//#ifndef A_H_
//#define A_H_

View file

@ -0,0 +1,180 @@
/*******************************************************************************
* Copyright (c) 2012, 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.refactoring.includes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import junit.framework.TestSuite;
import com.ibm.icu.text.MessageFormat;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.testplugin.util.OneSourceMultipleHeadersTestCase;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
import org.eclipse.cdt.internal.ui.refactoring.includes.BindingClassifier;
import org.eclipse.cdt.internal.ui.refactoring.includes.InclusionContext;
public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
private IIndex fIndex;
private InclusionContext fContext;
private BindingClassifier fBindingClassifier;
public BindingClassifierTest() {
super(new TestSourceReader(CTestPlugin.getDefault().getBundle(), "ui", BindingClassifierTest.class), true);
}
public static TestSuite suite() {
return suite(BindingClassifierTest.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
IASTTranslationUnit ast = getAst();
fIndex = CCorePlugin.getIndexManager().getIndex(getCProject(),
IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_EXTENSION_FRAGMENTS_ADD_IMPORT);
fIndex.acquireReadLock();
ITranslationUnit tu = ast.getOriginatingTranslationUnit();
fContext = new InclusionContext(tu, fIndex);
fBindingClassifier = new BindingClassifier(fContext);
fBindingClassifier.classifyNodeContents(ast);
}
@Override
protected void tearDown() throws Exception {
fIndex.releaseReadLock();
super.tearDown();
}
private void assertDefined(String... names) {
assertExpectedBindings(names, fBindingClassifier.getBindingsToDefine(), "defined");
}
private void assertDeclared(String... names) {
assertExpectedBindings(names, fBindingClassifier.getBindingsToDeclare(), "declared");
}
private void assertExpectedBindings(String[] expectedNames, Set<IBinding> bindings, String verb) {
Set<String> expected = new TreeSet<String>(Arrays.asList(expectedNames));
Set<String> extra = new TreeSet<String>();
for (IBinding binding : bindings) {
extra.add(binding.getName());
}
Set<String> missing = new TreeSet<String>(expected);
missing.removeAll(extra);
extra.removeAll(expected);
if (extra.isEmpty() && missing.isEmpty())
return;
List<String> errors = new ArrayList<String>(2);
if (!missing.isEmpty()) {
errors.add(MessageFormat.format("{0,choice,1#Binding|1<Bindings} \"{1}\" {0,choice,1#is|1<are} not {2}.",
missing.size(), join(missing, "\", \""), verb));
}
if (!extra.isEmpty()) {
errors.add(MessageFormat.format("{0,choice,1#Binding|1<Bindings} \"{1}\" should not be {2}.",
extra.size(), join(extra, "\", \""), verb));
}
fail(join(errors, " "));
}
private String join(Iterable<String> strings, String delimiter) {
StringBuilder buf = new StringBuilder();
for (String str : strings) {
if (buf.length() != 0)
buf.append(delimiter);
buf.append(str);
}
return buf.toString();
}
// class A;
// typedef A* td1;
// typedef td1* td2;
// td2 f();
// A* a = *f();
public void testTypedef_1() throws Exception {
assertDefined("f");
assertDeclared("A");
}
// class A;
// typedef A* td1;
// typedef td1* td2;
// td2 f();
// td1 a = *f();
public void testTypedef_2() throws Exception {
assertDefined("f", "td1");
}
// class A { int x; };
// typedef A* td;
// td f();
// int a = f()->x;
public void testClassMember() throws Exception {
assertDefined("f", "A");
}
// class A { void m(); };
// void test(A* a) {
// a->m();
// }
public void testMethodCall() throws Exception {
assertDefined("A");
}
// struct A {};
// struct B {};
// struct C {
// A a;
// static B b;
// };
public void testFieldReference() throws Exception {
assertDefined("A");
assertDeclared("B");
}
// int a;
// void test() {
// void* x = &a;
// }
public void testVariableReference() throws Exception {
assertDefined("a"); // Forward declaration of variables is not allowed by default.
}
// struct A {
// void operator()(int p);
// };
// const A a;
// void test() {
// a(1);
// }
public void testCallOperator() throws Exception {
assertDefined("A", "a"); // Forward declaration of variables is not allowed by default.
}
}

View file

@ -0,0 +1,176 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.refactoring.includes;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.preference.IPreferenceStore;
import org.osgi.framework.Bundle;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
import org.eclipse.cdt.ui.tests.refactoring.TestSourceFile;
import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
/**
* Common base for include-related tests.
*/
public abstract class IncludesTestBase extends BaseTestCase {
protected final String LINE_DELIMITER = "\n";
protected static class FirstHeaderChooser implements IHeaderChooser {
@Override
public IPath chooseHeader(String bindingName, Collection<IPath> headers) {
return headers.isEmpty() ? null : headers.iterator().next();
}
}
/** Expected counts of errors, warnings and info messages */
protected int expectedInitialErrors;
protected int expectedInitialWarnings;
protected int expectedFinalWarnings;
protected int expectedFinalInfos;
protected IIndex index;
protected ICProject cproject;
protected IASTTranslationUnit ast;
protected TestSourceFile selectedFile;
private StringBuilder[] testData;
private boolean cpp = true;
private final Set<TestSourceFile> testFiles = new LinkedHashSet<TestSourceFile>();
protected IncludesTestBase() {
super();
}
protected IncludesTestBase(String name) {
super(name);
}
@Override
public void setUp() throws Exception {
super.setUp();
resetPreferences();
cproject = cpp ?
CProjectHelper.createCCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER) :
CProjectHelper.createCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
Bundle bundle = CTestPlugin.getDefault().getBundle();
CharSequence[] testData = TestSourceReader.getContentsForTest(bundle, "ui", getClass(), getName(), 0);
IFile sourceFile = null;
for (CharSequence contents : testData) {
TestSourceFile testFile = null;
boolean expectedResult = false;
BufferedReader reader = new BufferedReader(new StringReader(contents.toString()));
String line;
while ((line = reader.readLine()) != null) {
String trimmedLine = line.trim();
if (testFile == null) {
assertTrue("Invalid file name \"" + trimmedLine + "\"", trimmedLine.matches("^(\\w+/)*\\w+\\.\\w+$"));
testFile = new TestSourceFile(trimmedLine);
} else if (isResultDelimiter(trimmedLine)) {
expectedResult = true;
} else if (expectedResult) {
testFile.addLineToExpectedSource(line);
} else {
testFile.addLineToSource(line);
}
}
reader.close();
sourceFile = TestSourceReader.createFile(cproject.getProject(), new Path(testFile.getName()),
testFile.getSource());
testFiles.add(testFile);
selectedFile = testFile;
}
CCorePlugin.getIndexManager().setIndexerId(cproject, IPDOMManager.ID_FAST_INDEXER);
waitForIndexer(cproject);
index= CCorePlugin.getIndexManager().getIndex(cproject);
index.acquireReadLock();
ast = TestSourceReader.createIndexBasedAST(index, cproject, sourceFile);
}
@Override
public void tearDown() throws Exception {
if (cproject != null) {
cproject.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, npm());
}
resetPreferences();
super.tearDown();
}
protected ICProject getCProject() {
return cproject;
}
protected TestSourceFile getSelectedTestFile() {
return selectedFile;
}
protected IFile getSelectedFile() {
if (selectedFile == null)
return null;
return cproject.getProject().getFile(new Path(selectedFile.getName()));
}
protected ITranslationUnit getSelectedTranslationUnit() {
IFile file = getSelectedFile();
if (file == null)
return null;
return (ITranslationUnit) CoreModel.getDefault().create(file);
}
protected boolean isCpp() {
return cpp;
}
protected void setCpp(boolean cpp) {
this.cpp = cpp;
}
private boolean isResultDelimiter(String str) {
if (str.isEmpty())
return false;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) != '=')
return false;
}
return true;
}
protected void resetPreferences() {
}
protected IPreferenceStore getPreferenceStore() {
return CUIPlugin.getDefault().getPreferenceStore();
}
}

View file

@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.refactoring.includes;
import junit.framework.Test;
import junit.framework.TestSuite;
public class IncludesTestSuite extends TestSuite {
public static Test suite() throws Exception {
IncludesTestSuite suite = new IncludesTestSuite();
suite.addTest(BindingClassifierTest.suite());
suite.addTest(OrganizeIncludesTest.suite());
return suite;
}
}

View file

@ -0,0 +1,298 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.refactoring.includes;
import java.util.List;
import junit.framework.Test;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeOrganizer;
/**
* Tests for Extract Function refactoring.
*/
public class OrganizeIncludesTest extends IncludesTestBase {
public OrganizeIncludesTest() {
super();
}
public OrganizeIncludesTest(String name) {
super(name);
}
public static Test suite() {
return suite(OrganizeIncludesTest.class);
}
@Override
protected void resetPreferences() {
super.resetPreferences();
getPreferenceStore().setToDefault(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_ENUMS);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_TEMPLATES);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS);
getPreferenceStore().setToDefault(PreferenceConstants.INCLUDES_ALLOW_REORDERING);
}
private void assertExpectedResults() throws Exception {
String actual = organizeIncludes(ast.getOriginatingTranslationUnit());
assertEquals(selectedFile.getExpectedSource(), actual);
}
/**
* Invokes include organizer and returns the new contents of the translation unit.
*/
private String organizeIncludes(ITranslationUnit tu) throws Exception {
IHeaderChooser headerChooser = new FirstHeaderChooser();
IncludeOrganizer organizer = new IncludeOrganizer(tu, index, LINE_DELIMITER, headerChooser);
List<TextEdit> edits = organizer.organizeIncludes(ast);
IDocument document = new Document(new String(tu.getContents()));
if (!edits.isEmpty()) {
// Apply text edits.
MultiTextEdit edit = new MultiTextEdit();
edit.addChildren(edits.toArray(new TextEdit[edits.size()]));
edit.apply(document);
}
return document.get();
}
//h1.h
//typedef int my_type;
//A.h
//class A {
// my_type m1();
//};
//A.cpp
//// Comment line 1
//// Comment line 2
//
//// Comment for m1
//my_type A::m1() {
// return 0;
//}
//====================
//// Comment line 1
//// Comment line 2
//
//#include "A.h"
//
//#include "h1.h"
//
//// Comment for m1
//my_type A::m1() {
// return 0;
//}
public void testNoExistingIncludes() throws Exception {
assertExpectedResults();
}
//B.h
//class B {};
//C.h
//class C {};
//A.h
//#if !defined(INCLUDE_GUARD)
//#define INCLUDE_GUARD
//// Comment line 1
//// Comment line 2
//
//// Comment for A
//class A {
// B f;
// C m();
//};
//#endif // INCLUDE_GUARD
//====================
//#if !defined(INCLUDE_GUARD)
//#define INCLUDE_GUARD
//// Comment line 1
//// Comment line 2
//
//#include "B.h"
//
//class C;
//
//// Comment for A
//class A {
// B f;
// C m();
//};
//#endif // INCLUDE_GUARD
public void testIncludeGuards() throws Exception {
assertExpectedResults();
}
//B.h
//template <typename T> class B {};
//C.h
//class C {};
//A.h
//#pragma once
//namespace ns {
//// Comment line 1
//// Comment line 2
//
//// Comment for A
//class A : public B<C> {};
//} // namespace ns
//====================
//#pragma once
//
//#include "B.h"
//#include "C.h"
//
//namespace ns {
//// Comment line 1
//// Comment line 2
//
//// Comment for A
//class A : public B<C> {};
//} // namespace ns
public void testPragmaOnce() throws Exception {
assertExpectedResults();
}
//h1.h
//typedef int Type1;
//h2.h
//class Type2 {};
//h3.h
//enum Type3 { ONE, TWO };
//h4.h
//class Unrelated {};
//A.h
//#include "h1.h"
//class Type2;
//enum class Type3;
//extern Type1 f1();
//extern Type2 f2();
//extern Type3 f3();
//A.cpp
//// Comment
//
//#include "h2.h" /* Required */ // another comment
//#include "h1.h" // Unused
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
//====================
//// Comment
//
//#include "A.h"
//
////#include "h1.h" // Unused
//#include "h2.h" /* Required */ // another comment
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
public void testExistingIncludes() throws Exception {
assertExpectedResults();
}
//h1.h
//typedef int Type1;
//h2.h
//class Type2 {};
//h3.h
//enum class Type3 { ONE, TWO };
//h4.h
//class Unrelated {};
//A.h
//#include "h1.h"
//class Type2;
//enum class Type3;
//extern Type1 f1();
//extern Type2 f2();
//extern Type3 f3();
//A.cpp
//// Comment
//
//#include "h2.h" /* Required */ // another comment
//#include "h1.h" // Unused
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
//====================
//// Comment
//
//#include "h2.h" /* Required */ // another comment
////#include "h1.h" // Unused
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//#include "A.h"
//
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
public void testExistingIncludesNoReordering() throws Exception {
getPreferenceStore().setValue(PreferenceConstants.INCLUDES_ALLOW_REORDERING, false);
assertExpectedResults();
}
}

View file

@ -88,7 +88,7 @@ public class DefinitionFinderTest extends RefactoringTestBase {
for (IASTDeclaration declaration : ast.getDeclarations()) {
if (declaration instanceof IASTSimpleDeclaration) {
IASTName name = ((IASTSimpleDeclaration) declaration).getDeclarators()[0].getName();
assertNotNull(DefinitionFinder.getDefinition(name, refactoringContext, NULL_PROGRESS_MONITOR));
assertNotNull(DefinitionFinder.getDefinition(name, refactoringContext, npm()));
}
}
} finally {

View file

@ -42,6 +42,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true,
org.eclipse.cdt.internal.ui.refactoring.gettersandsetters;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.hidemethod;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.implementmethod;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.includes;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.rename;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.togglefunction;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.utils;x-friends:="org.eclipse.cdt.ui.tests",

View file

@ -1,5 +1,5 @@
###############################################################################
# Copyright (c) 2003, 2012 IBM Corporation, QNX Software Systems, and others.
# Copyright (c) 2003, 2013 IBM Corporation, QNX Software Systems, 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
@ -196,6 +196,8 @@ CPluginFileTypesPreferencePage.name=File Types
CodeStylePreferencePage.name=Code Style
codeTemplatePreferencePage.name=Code Templates
codeFormatterPreferencePage.name=Formatter
includeStylePreferencePage.name=Include Style
organizeIncludesPreferencePage.name=Organize Includes
nameStylePreferencePage.name=Name Style
CodeAssistPreferencePage.name=Content Assist
CodeAssistAdvancedPreferencePage.name=Advanced
@ -274,6 +276,10 @@ ActionDefinition.openType.description= Open an element in an Editor
ActionDefinition.addInclude.name= Add Include
ActionDefinition.addInclude.description= Create include statement on selection
#Organize Includes
ActionDefinition.addInclude.name= Organize Includes
ActionDefinition.addInclude.description= Evaluates all required includes and replaces the current includes
#Sort Lines
ActionDefinition.sortLines.name= Sort Lines
ActionDefinition.sortLines.description= Sort selected lines alphabetically
@ -566,7 +572,9 @@ preferenceKeywords.common=c cpp cplusplus cdt
preferenceKeywords.codeformatter=profile codestyle project specific comment indentation brace white space blank line new control statement wrapping tab parenthesis bracket
preferenceKeywords.codestyle=class member visibility order ordering
preferenceKeywords.codetemplates=comment code constructor method file type content
preferenceKeywords.namestyle=name file getter setter field variable
preferenceKeywords.namestyle=name style file getter setter field variable
preferenceKeywords.includestyle=include includes style partner system header file system
preferenceKeywords.organizeincludes=include includes organize
preferenceKeywords.todo=case sensitive task tag todo xxx fix fixme project comments
preferenceKeywords.indexer=index skip references type macro search build configuration cache memory performance
@ -589,6 +597,7 @@ renameParticipant.name = Source Folder Rename
FormatAction.label= &Format
IndentAction.label= Correct &Indentation
OrganizeIncludesAction.label= Or&ganize Includes
AddIncludeAction.label= A&dd Include
SortLinesAction.label= Sor&t Lines
CommentAction.label= Co&mment

View file

@ -1232,6 +1232,22 @@
<keywordReference id="org.eclipse.cdt.ui.namestyle"/>
<keywordReference id="org.eclipse.cdt.ui.common"/>
</page>
<page
name="%organizeIncludesPreferencePage.name"
category="org.eclipse.cdt.ui.preferences.CodeStylePreferencePage"
class="org.eclipse.cdt.internal.ui.preferences.OrganizeIncludesPreferencePage"
id="org.eclipse.cdt.ui.preferences.OrganizeIncludesPreferencePage">
<keywordReference id="org.eclipse.cdt.ui.organizeincludes"/>
<keywordReference id="org.eclipse.cdt.ui.common"/>
</page>
<page
name="%includeStylePreferencePage.name"
category="org.eclipse.cdt.ui.preferences.OrganizeIncludesPreferencePage"
class="org.eclipse.cdt.internal.ui.preferences.IncludeStylePreferencePage"
id="org.eclipse.cdt.ui.preferences.IncludeStylePreferencePage">
<keywordReference id="org.eclipse.cdt.ui.includestyle"/>
<keywordReference id="org.eclipse.cdt.ui.common"/>
</page>
<page
name="%markOccurrencesPreferencePage.name"
category="org.eclipse.cdt.ui.preferences.CEditorPreferencePage"
@ -1285,6 +1301,12 @@
<keyword
label="%preferenceKeywords.namestyle"
id="org.eclipse.cdt.ui.namestyle"/>
<keyword
label="%preferenceKeywords.includestyle"
id="org.eclipse.cdt.ui.includestyle"/>
<keyword
label="%preferenceKeywords.organizeincludes"
id="org.eclipse.cdt.ui.organizeincludes"/>
<keyword
label="%preferenceKeywords.codeformatter"
id="org.eclipse.cdt.ui.codeformatter"/>
@ -1862,6 +1884,13 @@
menubarPath="org.eclipse.jdt.ui.source.menu/importGroup"
id="org.eclipse.cdt.ui.actions.SortLines">
</action>
<action
definitionId="org.eclipse.cdt.ui.edit.text.c.organize.includes"
label="%OrganizeIncludesAction.label"
retarget="true"
menubarPath="org.eclipse.jdt.ui.source.menu/importGroup"
id="org.eclipse.cdt.ui.actions.OrganizeIncludes">
</action>
<action
definitionId="org.eclipse.cdt.ui.edit.text.c.add.include"
label="%AddIncludeAction.label"
@ -2429,6 +2458,11 @@
contextId="org.eclipse.cdt.ui.cViewScope"
commandId="org.eclipse.cdt.ui.navigate.open.type.in.hierarchy"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
<key
sequence="M1+M2+O"
contextId="org.eclipse.cdt.ui.cEditorScope"
commandId="org.eclipse.cdt.ui.edit.text.c.organize.includes"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
<key
sequence="M1+M2+N"
contextId="org.eclipse.cdt.ui.cEditorScope"
@ -2930,6 +2964,12 @@
categoryId="org.eclipse.cdt.ui.category.source"
id="org.eclipse.cdt.ui.edit.text.c.add.include">
</command>
<command
name="%ActionDefinition.organizeIncludes.name"
description="%ActionDefinition.OrganizeIncludes.description"
categoryId="org.eclipse.cdt.ui.category.source"
id="org.eclipse.cdt.ui.edit.text.c.organize.includes">
</command>
<command
name="%ActionDefinition.sortLines.name"
description="%ActionDefinition.sortLines.description"
@ -4586,6 +4626,7 @@
<key name="removeTrailingWhitespaceEditedLines"/>
<key name="Refactoring.savealleditors"/>
<key name="Refactor.lightweight"/>
<key name="organizeIncludes." match="prefix"/>
<key name="spelling_" match="prefix"/>
<key name="org.eclipse.cdt.ui.add_comments"/>
<key name="codetemplates.includeGuardGenerationScheme"/>
@ -4608,6 +4649,9 @@
<entry node="org.eclipse.cdt.ui">
<key name="codetemplates." match="prefix"/>
<key name="nameStyle." match="prefix"/>
<key name="includeStyle." match="prefix"/>
<key name="forwardDeclare." match="prefix"/>
<key name="includes.partnerFileSuffixes"/>
<key name="formatter_profile"/>
<key name="class_member_ascending_visibility_order"/>
<key name="function_output_parameters_before_input"/>

View file

@ -0,0 +1,145 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.cdt.ui.CUIPlugin;
/**
* Synchronously executes a {@link Job} while allowing user to cancel it if it takes too long.
*/
public final class BusyCursorJobRunner {
/**
* Adapts a {@link Job} to be an {@link IRunnableWithProgress}.
*/
private static class JobRunnableWithProgressAdapter implements IRunnableWithProgress {
private final Job job;
/**
* Creates the {@link IRunnableWithProgress} from the {@link Job}.
*/
public JobRunnableWithProgressAdapter(Job job) {
this.job = job;
}
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
IStatus result;
try {
monitor.beginTask(job.getName(), IProgressMonitor.UNKNOWN);
result = executeAndWait(job, monitor);
} catch (RuntimeException e) {
throw new InvocationTargetException(e);
}
switch (result.getSeverity()) {
case IStatus.CANCEL:
throw new InterruptedException();
case IStatus.ERROR:
if (result.getException() instanceof OperationCanceledException) {
throw new InterruptedException();
}
throw new InvocationTargetException(new CoreException(result));
}
}
}
/**
* Runs the given job and waits for it to finish. If executing in the UI thread, sets the cursor
* to busy while the job is being executed.
*
* @param job the job to execute
* @return the status reflecting the result of the job execution
*/
public static IStatus execute(Job job) {
boolean inUiThread = Thread.currentThread() == Display.getDefault().getThread();
if (inUiThread) {
return busyCursorWhile(job);
}
return executeAndWait(job, new NullProgressMonitor());
}
private static IStatus busyCursorWhile(Job job) {
try {
IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
progressService.busyCursorWhile(new JobRunnableWithProgressAdapter(job));
} catch (InterruptedException e) {
return Status.CANCEL_STATUS; // Operation was cancelled.
} catch (InvocationTargetException e) {
Throwable targetException = e.getTargetException();
if (targetException instanceof CoreException) {
return ((CoreException) targetException).getStatus();
}
return new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, e.getMessage(), e);
}
return Status.OK_STATUS;
}
private static IStatus executeAndWait(final Job job, IProgressMonitor monitor) {
final IStatus[] statusHolder = new IStatus[1];
IJobManager jobManager = Job.getJobManager();
JobChangeAdapter listener = new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
super.done(event);
if (event.getJob() == job) {
synchronized (statusHolder) {
statusHolder[0] = event.getResult();
statusHolder.notifyAll();
}
}
}
};
jobManager.addJobChangeListener(listener);
job.schedule();
try {
synchronized (statusHolder) {
while (statusHolder[0] == null) {
try {
statusHolder.wait(100);
if (monitor.isCanceled()) {
job.cancel();
}
} catch (InterruptedException e) {
job.cancel();
return Status.CANCEL_STATUS;
}
}
return statusHolder[0];
}
} finally {
monitor.done();
jobManager.removeJobChangeListener(listener);
}
}
private BusyCursorJobRunner() {}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 IBM Corporation and others.
* Copyright (c) 2006, 2013 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
@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* QNX Software System
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui;
@ -19,7 +20,6 @@ import org.eclipse.cdt.ui.CUIPlugin;
* <p>
* This interface contains constants only; it is not intended to be implemented or extended.
* </p>
*
*/
public interface ICHelpContextIds {
public static final String PREFIX = CUIPlugin.PLUGIN_ID + "."; //$NON-NLS-1$
@ -33,9 +33,10 @@ public interface ICHelpContextIds {
public static final String OPEN_PROJECT_WIZARD_ACTION = PREFIX + "open_project_wizard_action"; //$NON-NLS-1$
public static final String CONVERT_TO_CCPP_WIZARD_PAGE = PREFIX + "cdt_t_conv_proj_context"; //$NON-NLS-1$
public static final String NEW_C_FILE_WIZARD_PAGE = PREFIX + "cdt_creating_cpp_file_context"; //$NON-NLS-1$
// Actions
// Actions
public static final String ADD_INCLUDE_ON_SELECTION_ACTION = PREFIX + "add_includes_on_selection_action_context"; //$NON-NLS-1$;
public static final String ORGANIZE_INCLUDES_ACTION = PREFIX + "organize_includes_action"; //$NON-NLS-1$;
public static final String FILTER_PUBLIC_ACTION= PREFIX + "filter_public_action"; //$NON-NLS-1$
public static final String FILTER_FIELDS_ACTION= PREFIX + "filter_fields_action"; //$NON-NLS-1$
public static final String FILTER_STATIC_ACTION= PREFIX + "filter_static_action"; //$NON-NLS-1$
@ -87,6 +88,8 @@ public interface ICHelpContextIds {
public static final String SPELLING_CONFIGURATION_BLOCK= PREFIX + "spelling_configuration_block_context"; //$NON-NLS-1$
public static final String CODE_STYLE_PREFERENCE_PAGE = PREFIX + "code_style_preference_context"; //$NON-NLS-1$
public static final String CODE_TEMPLATES_PREFERENCE_PAGE = PREFIX + "code_templates_preference_context"; //$NON-NLS-1$
public static final String INCLUDE_STYLE_PREFERENCE_PAGE = PREFIX + "include_style_preference_context"; //$NON-NLS-1$
public static final String ORGANIZE_INCLUDES_PREFERENCE_PAGE = PREFIX + "organize_includes_preference_context"; //$NON-NLS-1$
public static final String NAME_STYLE_PREFERENCE_PAGE = PREFIX + "name_style_preference_context"; //$NON-NLS-1$
// Console view

View file

@ -33,14 +33,14 @@ import org.eclipse.ui.texteditor.RetargetTextEditorAction;
import org.eclipse.cdt.ui.actions.CdtActionConstants;
import org.eclipse.cdt.internal.ui.IContextMenuConstants;
import org.eclipse.cdt.internal.ui.actions.FindWordAction;
import org.eclipse.cdt.internal.ui.actions.GoToNextPreviousMemberAction;
import org.eclipse.cdt.internal.ui.actions.GotoNextBookmarkAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectEnclosingAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectHistoryAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectNextAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectPreviousAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectionAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectEnclosingAction;
import org.eclipse.cdt.internal.ui.actions.FindWordAction;
import org.eclipse.cdt.internal.ui.actions.GoToNextPreviousMemberAction;
import org.eclipse.cdt.internal.ui.actions.GotoNextBookmarkAction;
public class CEditorActionContributor extends TextEditorActionContributor {
@ -229,6 +229,7 @@ public class CEditorActionContributor extends TextEditorActionContributor {
bars.setGlobalActionHandler(CdtActionConstants.REMOVE_BLOCK_COMMENT, getAction(textEditor, "RemoveBlockComment")); //$NON-NLS-1$
bars.setGlobalActionHandler(CdtActionConstants.INDENT, getAction(textEditor, "Indent")); //$NON-NLS-1$
bars.setGlobalActionHandler(CdtActionConstants.ADD_INCLUDE, getAction(textEditor, "AddIncludeOnSelection")); //$NON-NLS-1$
bars.setGlobalActionHandler(CdtActionConstants.ORGANIZE_INCLUDES, getAction(textEditor, "OrganizeIncludes")); //$NON-NLS-1$
bars.setGlobalActionHandler(CdtActionConstants.SORT_LINES, getAction(textEditor, "SortLines")); //$NON-NLS-1$
IAction action= getAction(textEditor, ITextEditorActionConstants.REFRESH);

View file

@ -36,6 +36,15 @@ public final class CEditorMessages extends NLS {
public static String AddIncludeOnSelection_insertion_failed;
public static String AddIncludeOnSelection_help_provider_error;
public static String AddIncludesOperation_description;
public static String OrganizeIncludes_label;
public static String OrganizeIncludes_description;
public static String OrganizeIncludes_action;
public static String OrganizeIncludes_error_title;
public static String OrganizeIncludes_insertion_failed;
public static String OrganizeIncludes_help_provider_error;
public static String OrganizeIncludes_failed;
public static String OrganizeIncludes_choose_header;
public static String OrganizeIncludesOperation_description;
public static String ShowInCView_description;
public static String ShowInCView_label;
public static String ShowInCView_tooltip;

View file

@ -1,5 +1,5 @@
#########################################
# Copyright (c) 2005, 2011 IBM Corporation and others.
# Copyright (c) 2005, 2012 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
@ -12,6 +12,7 @@
# Markus Schorn (Wind River Systems)
# Sergey Prigogin (Google)
# Tomasz Wesolowski
# Mathias Kunter
#########################################
AddIncludeOnSelection_label=Add Include
@ -21,6 +22,16 @@ AddIncludeOnSelection_insertion_failed=Adding include statements failed
AddIncludeOnSelection_help_provider_error=Help provider error
AddIncludesOperation_description=Adding include statement
OrganizeIncludes_label=Organize Includes
OrganizeIncludes_description=Organize includes for current file
OrganizeIncludes_action=Organizing includes
OrganizeIncludes_error_title=Error Organizing Includes
OrganizeIncludes_insertion_failed=Adding include statements failed
OrganizeIncludes_help_provider_error=Help provider error
OrganizeIncludes_failed=Organize Includes operation failed
OrganizeIncludes_choose_header=Choose a header file to include for symbol ''{0}''
OrganizeIncludesOperation_description=Organizing include statements
ShowInCView_description=Show the current resource in the C/C++ Projects view
ShowInCView_label=Show in C/C++ Projects
ShowInCView_tooltip=Show current resource in C/C++ Projects view

View file

@ -18,6 +18,10 @@ AddIncludeOnSelection.label=A&dd Include
AddIncludeOnSelection.description=Add include statement for selected name
AddIncludeOnSelection.tooltip=Adds an include statement for selected name
OrganizeIncludes.label=Or&ganize Includes
OrganizeIncludes.tooltip=Evaluate All Required Includes and Replace the Current Ones
OrganizeIncludes.description=Evaluates all required includes and replaces the current ones
SortLines.label=Sort Lines
SortLines.tooltip=Sort Selected Lines Alphabetically
SortLines.description=Sorts selected lines alphabetically

View file

@ -72,6 +72,12 @@ public interface ICEditorActionDefinitionIds extends ITextEditorActionDefinition
*/
public static final String ADD_INCLUDE= "org.eclipse.cdt.ui.edit.text.c.add.include"; //$NON-NLS-1$
/**
* Action definition ID of the source -> organize includes action
* (value <code>"org.eclipse.cdt.ui.edit.text.c.organize.includes"</code>).
*/
public static final String ORGANIZE_INCLUDES= "org.eclipse.cdt.ui.edit.text.c.organize.includes"; //$NON-NLS-1$
/**
* Action definition ID of the open declaration action
* (value <code>"org.eclipse.cdt.ui.edit.opendecl"</code>).

View file

@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
/**
* Dialog-based header chooser.
*/
public class InteractiveHeaderChooser implements IHeaderChooser {
private final Shell shell;
Map<Collection<IPath>, IPath> userChoiceCache;
public InteractiveHeaderChooser(Shell shell) {
this.shell = shell;
userChoiceCache = new HashMap<Collection<IPath>, IPath>();
}
@Override
public IPath chooseHeader(final String bindingName, Collection<IPath> headers) {
if (headers.isEmpty())
return null;
if (headers.size() == 1)
return headers.iterator().next();
Set<IPath> cacheKey = new HashSet<IPath>(headers);
// Check the decision cache. If the cache doesn't help, ask the user.
// Query the cache.
if (userChoiceCache.containsKey(cacheKey)) {
return userChoiceCache.get(cacheKey);
}
// Ask the user.
final IPath[] elemArray = headers.toArray(new IPath[headers.size()]);
final IPath[] selectedElement = new IPath[1];
runInUIThread(new Runnable() {
@Override
public void run() {
if (!shell.isDisposed()) {
ElementListSelectionDialog dialog =
new ElementListSelectionDialog(shell, new LabelProvider());
dialog.setElements(elemArray);
dialog.setTitle(CEditorMessages.OrganizeIncludes_label);
dialog.setMessage(NLS.bind(CEditorMessages.OrganizeIncludes_choose_header, bindingName));
if (dialog.open() == Window.OK) {
selectedElement[0] = (IPath) dialog.getFirstResult();
}
}
}
});
IPath selectedHeader = selectedElement[0];
if (selectedHeader != null)
userChoiceCache.put(headers, selectedHeader); // Remember user's choice.
return selectedHeader;
}
private void runInUIThread(Runnable runnable) {
if (Display.getCurrent() != null) {
runnable.run();
} else {
Display.getDefault().syncExec(runnable);
}
}
}

View file

@ -0,0 +1,146 @@
/*******************************************************************************
* Copyright (c) 2012 Mathias Kunter 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:
* Mathias Kunter - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.text.undo.DocumentUndoManagerRegistry;
import org.eclipse.text.undo.IDocumentUndoManager;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.TextEditorAction;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.SharedASTJob;
import org.eclipse.cdt.internal.ui.BusyCursorJobRunner;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeOrganizer;
/**
* Organizes the include directives and forward declarations of a source or header file.
*/
public class OrganizeIncludesAction extends TextEditorAction {
/**
* Constructor
* @param editor The editor on which this organize includes action should operate.
*/
public OrganizeIncludesAction(ITextEditor editor) {
super(CEditorMessages.getBundleForConstructedKeys(), "OrganizeIncludes.", editor); //$NON-NLS-1$
CUIPlugin.getDefault().getWorkbench().getHelpSystem().setHelp(this, ICHelpContextIds.ORGANIZE_INCLUDES_ACTION);
}
@Override
public void run() {
final ITextEditor editor = getTextEditor();
final ITranslationUnit tu = getTranslationUnit(editor);
if (tu == null) {
return;
}
if (!validateEditorInputState()) {
return;
}
final IHeaderChooser headerChooser = new InteractiveHeaderChooser(editor.getSite().getShell());
final String lineDelimiter = getLineDelimiter(editor);
final List<TextEdit> edits = new ArrayList<TextEdit>();
SharedASTJob job = new SharedASTJob(CEditorMessages.OrganizeIncludes_action, tu) {
@Override
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
IIndex index= CCorePlugin.getIndexManager().getIndex(tu.getCProject(),
IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_EXTENSION_FRAGMENTS_ADD_IMPORT);
try {
index.acquireReadLock();
IncludeOrganizer organizer = new IncludeOrganizer(tu, index, lineDelimiter, headerChooser);
edits.addAll(organizer.organizeIncludes(ast));
return Status.OK_STATUS;
} catch (InterruptedException e) {
return Status.CANCEL_STATUS;
} finally {
index.releaseReadLock();
}
}
};
IStatus status = BusyCursorJobRunner.execute(job);
if (status.isOK()) {
if (!edits.isEmpty()) {
// Apply text edits.
MultiTextEdit edit = new MultiTextEdit();
edit.addChildren(edits.toArray(new TextEdit[edits.size()]));
IEditorInput editorInput = editor.getEditorInput();
IDocument document = editor.getDocumentProvider().getDocument(editorInput);
IDocumentUndoManager manager= DocumentUndoManagerRegistry.getDocumentUndoManager(document);
manager.beginCompoundChange();
try {
edit.apply(document);
} catch (MalformedTreeException e) {
CUIPlugin.log(e);
} catch (BadLocationException e) {
CUIPlugin.log(e);
}
manager.endCompoundChange();
}
} else if (status.matches(IStatus.ERROR)) {
ErrorDialog.openError(editor.getEditorSite().getShell(),
CEditorMessages.OrganizeIncludes_error_title,
CEditorMessages.OrganizeIncludes_insertion_failed, status);
}
}
private static String getLineDelimiter(ITextEditor editor) {
try {
IEditorInput editorInput = editor.getEditorInput();
IDocument document = editor.getDocumentProvider().getDocument(editorInput);
String delim= document.getLineDelimiter(0);
if (delim != null) {
return delim;
}
} catch (BadLocationException e) {
}
return System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$
}
@Override
public void update() {
ITextEditor editor = getTextEditor();
setEnabled(editor != null && getTranslationUnit(editor) != null);
}
/**
* Returns the translation unit of the given editor.
* @param editor The editor.
* @return The translation unit.
*/
private static ITranslationUnit getTranslationUnit(ITextEditor editor) {
if (editor == null) {
return null;
}
return CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput());
}
}

View file

@ -0,0 +1,293 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle.IncludeKind;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.ITreeListAdapter;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.TreeListDialogField;
/**
* The preference block for configuring styles of different categories of include statements.
*/
public class IncludeCategoriesBlock extends OptionsConfigurationBlock {
private final List<IncludeGroupStyle> styles;
private final Map<IncludeKind, Category> categories = new HashMap<IncludeKind, Category>();
private TreeListDialogField<Category> categoryTree;
private PixelConverter pixelConverter;
private StackLayout editorAreaStack;
private Category selectedCategory;
public IncludeCategoriesBlock(IStatusChangeListener context, IProject project,
IWorkbenchPreferenceContainer container, List<IncludeGroupStyle> styles) {
super(context, project, new Key[0], container);
this.styles = styles;
createCategories();
}
private void createCategories() {
createCategory(IncludeKind.RELATED);
createCategory(IncludeKind.PARTNER);
createCategory(IncludeKind.IN_SAME_FOLDER);
createCategory(IncludeKind.IN_SUBFOLDER);
createCategory(IncludeKind.SYSTEM);
createCategory(IncludeKind.SYSTEM_WITH_EXTENSION);
createCategory(IncludeKind.SYSTEM_WITHOUT_EXTENSION);
createCategory(IncludeKind.OTHER);
createCategory(IncludeKind.IN_SAME_PROJECT);
createCategory(IncludeKind.IN_OTHER_PROJECT);
createCategory(IncludeKind.EXTERNAL);
}
private Category createCategory(IncludeKind includeKind) {
Category parentCategory = categories.get(includeKind.parent);
Category category = new Category(includeKind, parentCategory);
categories.put(category.getIncludeKind(), category);
return category;
}
public void postSetSelection(Object element) {
categoryTree.postSetSelection(new StructuredSelection(element));
}
@Override
protected Control createContents(Composite parent) {
pixelConverter = new PixelConverter(parent);
setShell(parent.getShell());
Composite composite = new Composite(parent, SWT.NONE);
composite.setFont(parent.getFont());
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
composite.setLayout(layout);
IncludeStyleAdapter adapter = new IncludeStyleAdapter();
categoryTree = new TreeListDialogField<Category>(adapter, null, new IncludeStyleLabelProvider());
categoryTree.setDialogFieldListener(adapter);
categoryTree.setLabelText(PreferencesMessages.IncludeCategoriesBlock_header_categories);
categoryTree.setViewerComparator(adapter);
for (Category category : categories.values()) {
if (category.parent == null)
categoryTree.addElement(category);
}
Label label = categoryTree.getLabelControl(composite);
label.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false));
Control tree = categoryTree.getTreeControl(composite);
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
gd.widthHint = pixelConverter.convertWidthInCharsToPixels(50);
gd.heightHint = pixelConverter.convertHeightInCharsToPixels(2);
tree.setLayoutData(gd);
createCategoryEditors(composite);
categoryTree.setTreeExpansionLevel(2);
categoryTree.selectFirstElement();
updateControls();
return composite;
}
private void createCategoryEditors(Composite parent) {
Composite editorArea = new Composite(parent, SWT.NONE);
editorArea.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
editorArea.setFont(parent.getFont());
editorAreaStack = new StackLayout();
editorArea.setLayout(editorAreaStack);
Map<IncludeKind, IncludeGroupStyle> stylesByKind = new HashMap<IncludeKind, IncludeGroupStyle>();
for (IncludeGroupStyle style : styles) {
if (style.getIncludeKind() != IncludeKind.MATCHING_PATTERN)
stylesByKind.put(style.getIncludeKind(), style);
}
for (Category category : categories.values()) {
IncludeGroupStyleBlock block = new IncludeGroupStyleBlock(fContext, fProject, fContainer,
category.getDescription());
IncludeGroupStyle style = stylesByKind.get(category.getIncludeKind());
block.setStyle(style);
Control composite = block.createContents(editorArea);
category.setEditor(block, composite);
}
}
@Override
protected void updateControls() {
super.updateControls();
// Refresh
categoryTree.refresh();
updateConfigurationBlock(categoryTree.getSelectedElements());
for (Category category : categories.values()) {
category.getEditor().updateControls();
}
}
private void updateConfigurationBlock(List<Object> selection) {
if (selection.size() == 0)
return;
selectedCategory = (Category) selection.get(0);
editorAreaStack.topControl = selectedCategory.getEditorArea();
editorAreaStack.topControl.getParent().layout();
}
@Override
protected void validateSettings(Key changedKey, String oldValue, String newValue) {
fContext.statusChanged(new StatusInfo());
}
/**
* Represents a category of settings.
*/
private final static class Category {
public final Category parent;
public final int index; // Index in the siblings list
private final List<Category> children;
private final IncludeKind includeKind;
private Control editorArea;
private IncludeGroupStyleBlock editor;
Category(IncludeKind includeKind, Category parent) {
this.includeKind = includeKind;
this.parent = parent;
children = new ArrayList<Category>();
index = parent != null ? parent.addChild(this) : 0;
}
private int addChild(Category category) {
children.add(category);
return children.size() - 1;
}
Category[] getChildren() {
return children.toArray(new Category[children.size()]);
}
boolean hasChildren() {
return !children.isEmpty();
}
@Override
public String toString() {
return includeKind.name;
}
IncludeKind getIncludeKind() {
return includeKind;
}
IncludeGroupStyleBlock getEditor() {
return editor;
}
Control getEditorArea() {
return editorArea;
}
void setEditor(IncludeGroupStyleBlock editor, Control editorArea) {
this.editor = editor;
this.editorArea = editorArea;
}
String getName() {
return includeKind.name;
}
String getDescription() {
return includeKind.description;
}
}
private class IncludeStyleAdapter extends ViewerComparator
implements ITreeListAdapter<Category>, IDialogFieldListener {
@Override
public void selectionChanged(TreeListDialogField<Category> field) {
updateConfigurationBlock(field.getSelectedElements());
}
@Override
public void customButtonPressed(TreeListDialogField<Category> field, int index) {
}
@Override
public void doubleClicked(TreeListDialogField<Category> field) {
}
@Override
public Category[] getChildren(TreeListDialogField<Category> field, Object element) {
return ((Category) element).getChildren();
}
@Override
public Category getParent(TreeListDialogField<Category> field, Object element) {
return ((Category) element).parent;
}
@Override
public boolean hasChildren(TreeListDialogField<Category> field, Object element) {
return ((Category) element).hasChildren();
}
@Override
public void dialogFieldChanged(DialogField field) {
}
@Override
public void keyPressed(TreeListDialogField<Category> field, KeyEvent event) {
}
@Override
public int category(Object element) {
return ((Category) element).index;
}
}
private static class IncludeStyleLabelProvider extends LabelProvider {
@Override
public Image getImage(Object element) {
return null;
}
@Override
public String getText(Object element) {
return ((Category) element).getName();
}
}
}

View file

@ -0,0 +1,205 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import java.util.ArrayList;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.cdt.utils.ui.controls.ControlFactory;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle;
/**
* The preference block for configuring styles of different categories of include statements.
*/
public class IncludeGroupStyleBlock extends OptionsConfigurationBlock {
private final String description;
private IncludeGroupStyle style;
private final ArrayList<Button> checkBoxes = new ArrayList<Button>();
private final ArrayList<Text> textBoxes = new ArrayList<Text>();
private PixelConverter pixelConverter;
private Button checkBoxBlankLine;
private static final Key[] EMPTY_KEY_ARRAY = {};
public IncludeGroupStyleBlock(IStatusChangeListener context, IProject project,
IWorkbenchPreferenceContainer container, String description) {
super(context, project, EMPTY_KEY_ARRAY, container);
this.description = description;
}
public IncludeGroupStyle getStyle() {
return style;
}
public void setStyle(IncludeGroupStyle style) {
this.style = style;
}
@Override
protected Control createContents(Composite parent) {
pixelConverter = new PixelConverter(parent);
setShell(parent.getShell());
Composite composite = new Composite(parent, SWT.NONE);
composite.setFont(parent.getFont());
GridLayout layout = new GridLayout();
layout.marginHeight = pixelConverter.convertHeightInCharsToPixels(1);
layout.marginWidth = 0;
composite.setLayout(layout);
composite.setFont(parent.getFont());
Group group = ControlFactory.createGroup(composite, description, 1);
group.setLayoutData(new GridData(GridData.FILL_BOTH));
Composite envelope = new Composite(group, SWT.NONE);
layout = new GridLayout(4, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
envelope.setLayout(layout);
addCheckBox(envelope, PreferencesMessages.IncludeGroupStyleBlock_keep_includes_together, 0,
new BooleanDataSource() {
@Override
public boolean get() {
return style.isKeepTogether();
}
@Override
public void set(boolean value) {
style.setKeepTogether(value);
}
});
checkBoxBlankLine = addCheckBox(envelope, PreferencesMessages.IncludeGroupStyleBlock_blank_line_before,
pixelConverter.convertHorizontalDLUsToPixels(10),
new BooleanDataSource() {
@Override
public boolean get() {
return style.isBlankLineBefore();
}
@Override
public void set(boolean value) {
style.setBlankLineBefore(value);
}
});
if (!style.getIncludeKind().hasChildren()) {
addCheckBox(envelope, PreferencesMessages.IncludeGroupStyleBlock_use_relative_path, 0,
new BooleanDataSource() {
@Override
public boolean get() {
return style.isRelativePath();
}
@Override
public void set(boolean value) {
style.setRelativePath(value);
}
});
addCheckBox(envelope, PreferencesMessages.IncludeGroupStyleBlock_use_angle_brackets, 0,
new BooleanDataSource() {
@Override
public boolean get() {
return style.isAngleBrackets();
}
@Override
public void set(boolean value) {
style.setAngleBrackets(value);
}
});
}
updateControls();
updateDependent();
return composite;
}
private Button addCheckBox(Composite parent, String label, int indent, BooleanDataSource dataSource) {
GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= 3;
gd.horizontalIndent= indent;
Button checkBox= new Button(parent, SWT.CHECK);
checkBox.setFont(JFaceResources.getDialogFont());
checkBox.setText(label);
checkBox.setData(dataSource);
checkBox.setLayoutData(gd);
checkBox.addSelectionListener(getSelectionListener());
makeScrollableCompositeAware(checkBox);
checkBox.setSelection(dataSource.get());
checkBoxes.add(checkBox);
return checkBox;
}
@Override
protected void updateControls() {
super.updateControls();
for (int i= checkBoxes.size() - 1; i >= 0; i--) {
updateCheckBox(checkBoxes.get(i));
}
}
@Override
protected void updateCheckBox(Button checkBox) {
BooleanDataSource dataSource = (BooleanDataSource) checkBox.getData();
checkBox.setSelection(dataSource.get());
}
@Override
protected void controlChanged(Widget widget) {
if (widget instanceof Button) {
BooleanDataSource dataSource = (BooleanDataSource) widget.getData();
dataSource.set(((Button) widget).getSelection());
}
updateDependent();
}
private void updateDependent() {
checkBoxBlankLine.setEnabled(style.isKeepTogether());
}
@Override
protected void validateSettings(Key changedKey, String oldValue, String newValue) {
StatusInfo status = new StatusInfo();
fContext.statusChanged(status);
}
private interface BooleanDataSource {
boolean get();
void set(boolean value);
}
private interface StringDataSource {
String get();
void set(String value);
}
}

View file

@ -0,0 +1,338 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle.IncludeKind;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.ListDialogField;
/**
* The preference block for configuring relative order of include statements.
*/
public class IncludeOrderBlock extends OptionsConfigurationBlock {
private static final int IDX_UP = 0;
private static final int IDX_DOWN = 1;
private static final String[] UP_DOWN_LABELS = {
PreferencesMessages.IncludeOrderBlock_up,
PreferencesMessages.IncludeOrderBlock_down
};
private final List<IncludeGroupStyle> styles;
private Map<IncludeKind, IncludeGroupStyle> stylesByKind;
private GroupListField includeGroupList;
private PixelConverter pixelConverter;
public IncludeOrderBlock(IStatusChangeListener context, IProject project,
IWorkbenchPreferenceContainer container, List<IncludeGroupStyle> styles) {
super(context, project, new Key[0], container);
this.styles = styles;
}
@Override
protected Control createContents(Composite parent) {
pixelConverter = new PixelConverter(parent);
setShell(parent.getShell());
Composite composite = new Composite(parent, SWT.NONE);
composite.setFont(parent.getFont());
GridLayout layout = new GridLayout(2, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
composite.setLayout(layout);
includeGroupList = new GroupListField();
includeGroupList.setLabelText(PreferencesMessages.IncludeOrderBlock_order_of_includes);
Label label = includeGroupList.getLabelControl(composite);
label.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false, 2, 1));
Control control = includeGroupList.getListControl(composite);
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
gd.widthHint = pixelConverter.convertWidthInCharsToPixels(50);
gd.heightHint = pixelConverter.convertHeightInCharsToPixels(5);
control.setLayoutData(gd);
Control buttonsControl = includeGroupList.getButtonBox(composite);
buttonsControl.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false));
updateControls();
return composite;
}
@Override
protected void updateControls() {
super.updateControls();
stylesByKind = getStylesByKind(styles);
List<IncludeGroupStyle> orderedStyles = new ArrayList<IncludeGroupStyle>(styles);
Collections.sort(orderedStyles); // Sort according to values returned by getOrder() method.
List<IncludeGroupStyle> groupedStyles = new ArrayList<IncludeGroupStyle>();
int order = 0;
for (IncludeGroupStyle style : orderedStyles) {
style.setOrder(order++);
IncludeKind includeKind = style.getIncludeKind();
if (style.isKeepTogether() &&
(!includeKind.hasChildren() || hasUngroupedChildren(includeKind, stylesByKind))) {
groupedStyles.add(style);
}
}
// Adjust order of groups to satisfy higher order grouping.
for (int i = 0; i < groupedStyles.size(); i++) {
IncludeGroupStyle style = groupedStyles.get(i);
IncludeKind groupingKind = getGroupingParentKind(style);
if (groupingKind != null) {
while (++i < groupedStyles.size() && getGroupingParentKind(groupedStyles.get(i)) == groupingKind) {}
for (int j = i + 1; j < groupedStyles.size(); j++) {
if (getGroupingParentKind(groupedStyles.get(j)) == groupingKind) {
groupedStyles.add(i++, groupedStyles.remove(j));
}
}
}
}
includeGroupList.setElements(groupedStyles);
}
private boolean areKeptTogether(IncludeGroupStyle style1, IncludeGroupStyle style2) {
IncludeKind kind = getGroupingParentKind(style1);
return kind != null && kind == getGroupingParentKind(style2);
}
private IncludeKind getGroupingParentKind(IncludeGroupStyle style) {
IncludeKind kind = style.getIncludeKind().parent;
if (kind == null)
return null;
while (true) {
// "Other" include kind is special since it applies only to non grouped includes.
if (kind == IncludeKind.OTHER && style.isKeepTogether())
break;
IncludeGroupStyle parent = stylesByKind.get(kind);
if (parent != null && parent.isKeepTogether())
return kind;
if (kind == IncludeKind.OTHER)
break;
kind = IncludeKind.OTHER;
}
return null;
}
private static Map<IncludeKind, IncludeGroupStyle> getStylesByKind(List<IncludeGroupStyle> styles) {
Map<IncludeKind, IncludeGroupStyle> stylesByKind = new HashMap<IncludeKind, IncludeGroupStyle>();
for (IncludeGroupStyle style : styles) {
if (style.getIncludeKind() != IncludeKind.MATCHING_PATTERN)
stylesByKind.put(style.getIncludeKind(), style);
}
return stylesByKind;
}
private boolean hasUngroupedChildren(IncludeKind includeKind, Map<IncludeKind, IncludeGroupStyle> stylesByKind) {
// This code relies on the fact that IncludeKind hierarchy is only two levels deep.
for (IncludeKind childKind : includeKind.children) {
if (!stylesByKind.get(childKind).isKeepTogether())
return true;
}
// "Other" include kind is special since it effectively includes all other ungrouped includes.
if (includeKind == IncludeKind.OTHER) {
for (IncludeKind kind : stylesByKind.keySet()) {
if (kind != IncludeKind.OTHER && kind.hasChildren() && !stylesByKind.get(kind).isKeepTogether() &&
hasUngroupedChildren(kind, stylesByKind)) {
return true;
}
}
}
return false;
}
@Override
protected void validateSettings(Key changedKey, String oldValue, String newValue) {
fContext.statusChanged(new StatusInfo());
}
private class GroupListField extends ListDialogField<IncludeGroupStyle> {
GroupListField() {
super(null, UP_DOWN_LABELS, new GroupLabelProvider());
}
@Override
public void dialogFieldChanged() {
super.dialogFieldChanged();
int order = 0;
for (IncludeGroupStyle style : getElements()) {
style.setOrder(order++);
}
}
@Override
protected boolean getManagedButtonState(ISelection sel, int index) {
if (index == IDX_UP) {
return !sel.isEmpty() && canMoveUp();
} else if (index == IDX_DOWN) {
return !sel.isEmpty() && canMoveDown();
}
return true;
}
@Override
protected boolean managedButtonPressed(int index) {
if (index == IDX_UP) {
up();
} else if (index == IDX_DOWN) {
down();
} else {
return false;
}
return true;
}
private void up() {
boolean[] selected = getSelectionMask(false);
extendSelectionForMovingUp(selected, fElements);
if (selected != null) {
setElements(moveUp(fElements, selected));
fTable.reveal(fElements.get(getFirstSelected(selected)));
}
}
private void down() {
boolean[] selected = getSelectionMask(true);
List<IncludeGroupStyle> reversed = reverse(fElements);
extendSelectionForMovingUp(selected, reversed);
if (selected != null) {
setElements(reverse(moveUp(reversed, selected)));
fTable.reveal(fElements.get(getFirstSelected(selected)));
}
}
private List<IncludeGroupStyle> reverse(List<IncludeGroupStyle> p) {
List<IncludeGroupStyle> reverse = new ArrayList<IncludeGroupStyle>(p.size());
for (int i = p.size(); --i >= 0;) {
reverse.add(p.get(i));
}
return reverse;
}
private boolean[] getSelectionMask(boolean reverse) {
boolean[] selectionMask = null;
if (isOkToUse(fTableControl)) {
int nElements = fElements.size();
for (int i : fTable.getTable().getSelectionIndices()) {
if (selectionMask == null)
selectionMask = new boolean[nElements];
selectionMask[reverse ? nElements - 1 - i : i] = true;
}
}
return selectionMask;
}
private void extendSelectionForMovingUp(boolean[] selection, List<IncludeGroupStyle> styles) {
for (int i = 1; i < selection.length; i++) {
int j = i - 1;
if (!selection[i] && selection[j] && areKeptTogether(styles.get(i), styles.get(j))) {
selection[i] = true;
}
}
}
private List<IncludeGroupStyle> moveUp(List<IncludeGroupStyle> elements, boolean[] selected) {
int nElements= elements.size();
List<IncludeGroupStyle> res = new ArrayList<IncludeGroupStyle>(nElements);
List<IncludeGroupStyle> floating = new ArrayList<IncludeGroupStyle>();
for (int i = 0; i < nElements; i++) {
IncludeGroupStyle curr = elements.get(i);
if (selected[i]) {
res.add(curr);
} else {
if (!floating.isEmpty() && !areKeptTogether(curr, floating.get(0))) {
res.addAll(floating);
floating.clear();
}
floating.add(curr);
}
}
res.addAll(floating);
return res;
}
private int getFirstSelected(boolean[] selected) {
for (int i = 0; i < selected.length; i++) {
if (selected[i])
return i;
}
return -1;
}
private boolean canMoveUp() {
boolean[] selected = getSelectionMask(false);
if (selected == null || selected[0])
return false;
return canMoveUp(fElements, selected);
}
private boolean canMoveDown() {
boolean[] selected = getSelectionMask(true);
if (selected == null || selected[0])
return false;
return canMoveUp(reverse(fElements), selected);
}
private boolean canMoveUp(List<IncludeGroupStyle> elements, boolean[] selected) {
for (int i = 1; i < selected.length; i++) {
int j = i - 1;
if (selected[i] && !selected[j] && areKeptTogether(elements.get(i), elements.get(j))) {
while (++i < selected.length && selected[i]) {}
if (!areKeptTogether(elements.get(i - 1), elements.get(j)))
return false; // Cannot break a group.
}
}
return true;
}
}
private static class GroupLabelProvider extends LabelProvider {
@Override
public Image getImage(Object element) {
return null;
}
@Override
public String getText(Object element) {
IncludeGroupStyle style = (IncludeGroupStyle) element;
String name = style.getName();
if (name == null) {
name = style.getIncludeKind().name;
}
return name;
}
}
}

View file

@ -0,0 +1,123 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle.IncludeKind;
/**
* The preference block for configuring style of include statements.
*/
public class IncludeStyleBlock extends TabConfigurationBlock {
static final Key KEY_STYLE_RELATED = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_RELATED);
static final Key KEY_STYLE_PARTNER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_PARTNER);
static final Key KEY_STYLE_SAME_FOLDER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SAME_FOLDER);
static final Key KEY_STYLE_SUBFOLDER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SUBFOLDER);
static final Key KEY_STYLE_SYSTEM = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SYSTEM);
static final Key KEY_STYLE_SYSTEM_WITH_EXTENSION = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITH_EXTENSION);
static final Key KEY_STYLE_SYSTEM_WITHOUT_EXTENSION = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION);
static final Key KEY_STYLE_OTHER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_OTHER);
static final Key KEY_STYLE_SAME_PROJECT = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SAME_PROJECT);
static final Key KEY_STYLE_OTHER_PROJECT = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_OTHER_PROJECT);
static final Key KEY_STYLE_EXTERNAL = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_EXTERNAL);
static final Key KEY_STYLE_MATCHING_PATTERN = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_MATCHING_PATTERN);
static final Map<IncludeKind, Key> KEY_MAP = createKeyMap();
static final Key[] STYLE_KEYS = KEY_MAP.values().toArray(new Key[KEY_MAP.size()]);
private static final String[] TAB_LABELS = {
PreferencesMessages.IncludeStyleBlock_categories_tab,
PreferencesMessages.IncludeStyleBlock_order_tab,
};
private final List<IncludeGroupStyle> styles;
public IncludeStyleBlock(IStatusChangeListener context, IProject project,
IWorkbenchPreferenceContainer container) {
this(context, project, container, new ArrayList<IncludeGroupStyle>());
}
private IncludeStyleBlock(IStatusChangeListener context, IProject project,
IWorkbenchPreferenceContainer container, List<IncludeGroupStyle> styles) {
super(context, project, createTabs(context, project, container, styles), TAB_LABELS, container);
this.styles = styles;
settingsUpdated();
}
private static OptionsConfigurationBlock[] createTabs(IStatusChangeListener context,
IProject project, IWorkbenchPreferenceContainer container, List<IncludeGroupStyle> styles) {
IncludeCategoriesBlock includeCategoriesBlock = new IncludeCategoriesBlock(context, project, container, styles);
IncludeOrderBlock includeOrderBlock = new IncludeOrderBlock(context, project, container, styles);
return new OptionsConfigurationBlock[] { includeCategoriesBlock, includeOrderBlock };
}
private static Map<IncludeKind, Key> createKeyMap() {
Map<IncludeKind, Key> map = new HashMap<IncludeKind, Key>();
map.put(IncludeKind.RELATED, KEY_STYLE_RELATED);
map.put(IncludeKind.PARTNER, KEY_STYLE_PARTNER);
map.put(IncludeKind.IN_SAME_FOLDER, KEY_STYLE_SAME_FOLDER);
map.put(IncludeKind.IN_SUBFOLDER, KEY_STYLE_SUBFOLDER);
map.put(IncludeKind.SYSTEM, KEY_STYLE_SYSTEM);
map.put(IncludeKind.SYSTEM_WITH_EXTENSION, KEY_STYLE_SYSTEM_WITH_EXTENSION);
map.put(IncludeKind.SYSTEM_WITHOUT_EXTENSION, KEY_STYLE_SYSTEM_WITHOUT_EXTENSION);
map.put(IncludeKind.OTHER, KEY_STYLE_OTHER);
map.put(IncludeKind.IN_SAME_PROJECT, KEY_STYLE_SAME_PROJECT);
map.put(IncludeKind.IN_OTHER_PROJECT, KEY_STYLE_OTHER_PROJECT);
map.put(IncludeKind.EXTERNAL, KEY_STYLE_EXTERNAL);
return Collections.unmodifiableMap(map);
}
@Override
protected boolean processChanges(IWorkbenchPreferenceContainer container) {
boolean result = super.processChanges(container);
for (IncludeGroupStyle style : styles) {
IncludeKind includeKind = style.getIncludeKind();
Key key = KEY_MAP.get(includeKind);
if (includeKind != IncludeKind.MATCHING_PATTERN) {
setValue(key, style.toString());
} else {
// TODO(sprigogin): Support custom include categories.
}
}
return result;
}
@Override
protected void settingsUpdated() {
if (styles != null) {
styles.clear();
for (Map.Entry<IncludeKind, Key> entry : KEY_MAP.entrySet()) {
IncludeKind includeKind = entry.getKey();
IncludeGroupStyle style = null;
String str = getValue(entry.getValue());
if (str != null)
style = IncludeGroupStyle.fromString(str, includeKind);
if (style == null)
style = new IncludeGroupStyle(includeKind);
styles.add(style);
}
}
// TODO Propagate styles to tabs.
super.settingsUpdated();
}
}

View file

@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
/*
* The preference page for configuring styles of include statements.
*/
public class IncludeStylePreferencePage extends ConfigurationBlockPropertyAndPreferencePage {
public static final String PREF_ID= "org.eclipse.cdt.ui.preferences.IncludeStylePreferencePage"; //$NON-NLS-1$
public static final String PROP_ID= "org.eclipse.cdt.ui.propertyPages.IncludeStylePreferencePage"; //$NON-NLS-1$
public IncludeStylePreferencePage() {
setPreferenceStore(CUIPlugin.getDefault().getPreferenceStore());
// Only used when the page is shown programmatically.
setTitle(PreferencesMessages.IncludeStylePreferencePage_title);
}
@Override
protected OptionsConfigurationBlock createConfigurationBlock(IWorkbenchPreferenceContainer container) {
return new IncludeStyleBlock(getNewStatusChangedListener(), getProject(), container);
}
@Override
protected String getHelpId() {
return ICHelpContextIds.INCLUDE_STYLE_PREFERENCE_PAGE;
}
@Override
protected String getPreferencePageId() {
return PREF_ID;
}
@Override
protected String getPropertyPageId() {
return null;
// TODO(sprigogin): Project specific settings
// return PROP_ID;
}
}

View file

@ -176,7 +176,7 @@ public abstract class OptionsConfigurationBlock {
private Shell fShell;
private final IWorkingCopyManager fManager;
private final IWorkbenchPreferenceContainer fContainer;
protected final IWorkbenchPreferenceContainer fContainer;
private Map<Key, String> fDisabledProjectSettings; // null when project specific settings are turned off
@ -536,7 +536,7 @@ public abstract class OptionsConfigurationBlock {
return null;
}
private void makeScrollableCompositeAware(Control control) {
protected void makeScrollableCompositeAware(Control control) {
ScrolledPageContent parentScrolledComposite= getParentScrolledComposite(control);
if (parentScrolledComposite != null) {
parentScrolledComposite.adaptChild(control);

View file

@ -0,0 +1,112 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import org.eclipse.core.resources.IProject;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences.UnusedStatementDisposition;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil;
/**
* The preference block for configuring Organize Includes command.
*/
public class OrganizeIncludesBlock extends OptionsConfigurationBlock {
private static final Key KEY_HEURISTIC_HEADER_SUBSTITUTION = getCDTUIKey(PreferenceConstants.INCLUDES_HEURISTIC_HEADER_SUBSTITUTION);
private static final Key KEY_INCLUDES_REORDERING = getCDTUIKey(PreferenceConstants.INCLUDES_ALLOW_REORDERING);
private static final Key KEY_UNUSED_STATEMENTS_DISPOSITION = getCDTUIKey(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION);
private static final Key KEY_FORWARD_DECLARE_COMPOSITE_TYPES = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES);
private static final Key KEY_FORWARD_DECLARE_ENUMS = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_ENUMS);
private static final Key KEY_FORWARD_DECLARE_FUNCTIONS = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS);
private static final Key KEY_FORWARD_DECLARE_TEMPLATES = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_TEMPLATES);
private static final Key KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS);
private static final String[] DISPOSITION_VALUES = {
UnusedStatementDisposition.REMOVE.toString(),
UnusedStatementDisposition.COMMENT_OUT.toString(),
UnusedStatementDisposition.KEEP.toString(),
};
private static final String[] DISPOSITION_LABELS = {
PreferencesMessages.OrganizeIncludesBlock_remove,
PreferencesMessages.OrganizeIncludesBlock_comment_out,
PreferencesMessages.OrganizeIncludesBlock_keep,
};
private static Key[] ALL_KEYS = {
KEY_HEURISTIC_HEADER_SUBSTITUTION,
KEY_INCLUDES_REORDERING,
KEY_UNUSED_STATEMENTS_DISPOSITION,
KEY_FORWARD_DECLARE_COMPOSITE_TYPES,
KEY_FORWARD_DECLARE_ENUMS,
KEY_FORWARD_DECLARE_FUNCTIONS,
KEY_FORWARD_DECLARE_TEMPLATES,
KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS,
};
public OrganizeIncludesBlock(IStatusChangeListener context, IProject project,
IWorkbenchPreferenceContainer container) {
super(context, project, ALL_KEYS, container);
}
@Override
protected Control createContents(Composite parent) {
setShell(parent.getShell());
Composite composite = new Composite(parent, SWT.NONE);
composite.setFont(parent.getFont());
GridLayout layout = new GridLayout(2, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
composite.setLayout(layout);
Control control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_allow_reordering,
KEY_INCLUDES_REORDERING, TRUE_FALSE, 0);
LayoutUtil.setHorizontalSpan(control, 2);
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_heuristic_header_substitution,
KEY_HEURISTIC_HEADER_SUBSTITUTION, TRUE_FALSE, 0);
LayoutUtil.setHorizontalSpan(control, 2);
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_forward_declare_composite_types,
KEY_FORWARD_DECLARE_COMPOSITE_TYPES, TRUE_FALSE, 0);
LayoutUtil.setHorizontalSpan(control, 2);
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_forward_declare_enums,
KEY_FORWARD_DECLARE_ENUMS, TRUE_FALSE, 0);
LayoutUtil.setHorizontalSpan(control, 2);
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_forward_declare_functions,
KEY_FORWARD_DECLARE_FUNCTIONS, TRUE_FALSE, 0);
LayoutUtil.setHorizontalSpan(control, 2);
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_forward_declare_templates,
KEY_FORWARD_DECLARE_TEMPLATES, TRUE_FALSE, 0);
LayoutUtil.setHorizontalSpan(control, 2);
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_forward_declare_namespace_elements,
KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS, TRUE_FALSE, 0);
LayoutUtil.setHorizontalSpan(control, 2);
control = addComboBox(composite, PreferencesMessages.OrganizeIncludesBlock_unused_statements,
KEY_UNUSED_STATEMENTS_DISPOSITION, DISPOSITION_VALUES, DISPOSITION_LABELS, 0);
LayoutUtil.setHorizontalSpan(getLabel(control), 1);
updateControls();
return composite;
}
@Override
protected void validateSettings(Key changedKey, String oldValue, String newValue) {
StatusInfo status = new StatusInfo();
fContext.statusChanged(status);
}
}

View file

@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
/*
* The preference page for configuring Organize Includes command.
*/
public class OrganizeIncludesPreferencePage extends ConfigurationBlockPropertyAndPreferencePage {
public static final String PREF_ID= "org.eclipse.cdt.ui.preferences.OrganizeIncludesPreferencePage"; //$NON-NLS-1$
public static final String PROP_ID= "org.eclipse.cdt.ui.propertyPages.OrganizeIncludesPreferencePage"; //$NON-NLS-1$
public OrganizeIncludesPreferencePage() {
setPreferenceStore(CUIPlugin.getDefault().getPreferenceStore());
// Only used when the page is shown programmatically.
setTitle(PreferencesMessages.OrganizeIncludesPreferencePage_title);
}
@Override
protected OptionsConfigurationBlock createConfigurationBlock(IWorkbenchPreferenceContainer container) {
return new OrganizeIncludesBlock(getNewStatusChangedListener(), getProject(), container);
}
@Override
protected String getHelpId() {
return ICHelpContextIds.ORGANIZE_INCLUDES_PREFERENCE_PAGE;
}
@Override
protected String getPreferencePageId() {
return PREF_ID;
}
@Override
protected String getPropertyPageId() {
return null;
// TODO(sprigogin): Project specific settings
// return PROP_ID;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2011 IBM Corporation and others.
* Copyright (c) 2000, 2013 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
@ -364,6 +364,42 @@ public final class PreferencesMessages extends NLS {
public static String CodeTemplateBlock_export_error_hidden;
public static String CodeTemplateBlock_export_error_canNotWrite;
public static String IncludeStylePreferencePage_title;
public static String IncludeStyleBlock_categories_tab;
public static String IncludeStyleBlock_order_tab;
public static String IncludeCategoriesBlock_external_headers_node;
public static String IncludeCategoriesBlock_external_headers_node_description;
public static String IncludeCategoriesBlock_unrelated_headers_node;
public static String IncludeCategoriesBlock_unrelated_headers_node_description;
public static String IncludeCategoriesBlock_other_project_headers_node;
public static String IncludeCategoriesBlock_other_project_headers_node_description;
public static String IncludeCategoriesBlock_partner_header_node;
public static String IncludeCategoriesBlock_partner_header_node_description;
public static String IncludeCategoriesBlock_same_project_headers_node;
public static String IncludeCategoriesBlock_same_project_headers_node_description;
public static String IncludeCategoriesBlock_related_headers_node;
public static String IncludeCategoriesBlock_related_headers_node_description;
public static String IncludeCategoriesBlock_same_folder_header_node;
public static String IncludeCategoriesBlock_same_folder_header_node_description;
public static String IncludeCategoriesBlock_subfolder_header_node;
public static String IncludeCategoriesBlock_subfolder_header_node_description;
public static String IncludeCategoriesBlock_system_headers_node;
public static String IncludeCategoriesBlock_system_headers_node_description;
public static String IncludeCategoriesBlock_system_headers_with_extension_node;
public static String IncludeCategoriesBlock_system_headers_with_extension_node_description;
public static String IncludeCategoriesBlock_system_headers_without_extension_node;
public static String IncludeCategoriesBlock_system_headers_without_extension_node_description;
public static String IncludeCategoriesBlock_user_defined_categories_node;
public static String IncludeCategoriesBlock_user_defined_categories_node_description;
public static String IncludeGroupStyleBlock_keep_includes_together;
public static String IncludeCategoriesBlock_header_categories;
public static String IncludeGroupStyleBlock_blank_line_before;
public static String IncludeGroupStyleBlock_use_relative_path;
public static String IncludeGroupStyleBlock_use_angle_brackets;
public static String IncludeOrderBlock_up;
public static String IncludeOrderBlock_down;
public static String IncludeOrderBlock_order_of_includes;
public static String NameStylePreferencePage_title;
public static String NameStyleBlock_code_node;
public static String NameStyleBlock_files_node;
@ -402,6 +438,19 @@ public final class PreferencesMessages extends NLS {
public static String NameStyleBlock_invalid_word_delimiter;
public static String NameStyleBlock_invalid_suffix;
public static String OrganizeIncludesPreferencePage_title;
public static String OrganizeIncludesBlock_allow_reordering;
public static String OrganizeIncludesBlock_forward_declare_composite_types;
public static String OrganizeIncludesBlock_forward_declare_enums;
public static String OrganizeIncludesBlock_forward_declare_functions;
public static String OrganizeIncludesBlock_forward_declare_templates;
public static String OrganizeIncludesBlock_forward_declare_namespace_elements;
public static String OrganizeIncludesBlock_heuristic_header_substitution;
public static String OrganizeIncludesBlock_unused_statements;
public static String OrganizeIncludesBlock_comment_out;
public static String OrganizeIncludesBlock_keep;
public static String OrganizeIncludesBlock_remove;
public static String EditTemplateDialog_error_noname;
public static String EditTemplateDialog_error_invalidName;
public static String EditTemplateDialog_title_new;

View file

@ -1,5 +1,5 @@
###############################################################################
# Copyright (c) 2000, 2011 IBM Corporation and others.
# Copyright (c) 2000, 2013 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
@ -38,7 +38,7 @@ CEditorPreferencePage_ContentAssistPage_autoActivationDelay=Dela&y (ms)
CEditorPreferencePage_ContentAssistPage_proposalFilterSelect=Completion Proposal Filter:
CEditorPreferencePage_ContentAssistPage_completionProposalBackgroundColor=Completion proposal background
CEditorPreferencePage_ContentAssistPage_completionProposalForegroundColor=Completion proposal foreground
CEditorPreferencePage_ContentAssistPage_completionProposalTimeoutErrMsg=Time must be >= 0 milli seconds
CEditorPreferencePage_ContentAssistPage_completionProposalTimeoutErrMsg=Timeout must be a positive number
CEditorPreferencePage_ContentAssistPage_completionProposalTimeout=Timeout for each proposal kind (ms):
CEditorPreferencePage_ContentAssistPage_completionProposalTimeoutToolTip=If a proposal kind has consumed more time for computation than defined here\nit is assumed that the computer is faulty.\nIn this case a dialog is showing up telling an appropriate message to the user.
CEditorPreferencePage_ContentAssistPage_parameterBackgroundColor=Parameter hint background
@ -419,6 +419,43 @@ CodeTemplateBlock_export_error_title= Export Templates
CodeTemplateBlock_export_error_hidden= Export failed.\n{0} is a hidden file.
CodeTemplateBlock_export_error_canNotWrite= Export failed.\n{0} cannot be modified.
IncludeStylePreferencePage_title= Include Style
IncludeStyleBlock_categories_tab= Categories
IncludeStyleBlock_order_tab= Order
IncludeCategoriesBlock_related_headers_node= Closely Related Headers
IncludeCategoriesBlock_related_headers_node_description= Closely related header files
IncludeCategoriesBlock_external_headers_node= External Headers
IncludeCategoriesBlock_external_headers_node_description= Header files outside workspace
IncludeCategoriesBlock_other_project_headers_node= Headers in Other Projects
IncludeCategoriesBlock_other_project_headers_node_description= Header files in other projects
IncludeCategoriesBlock_partner_header_node= Partner Header
IncludeCategoriesBlock_partner_header_node_description= Header file with the same name
IncludeCategoriesBlock_same_project_headers_node= Headers in Same Project
IncludeCategoriesBlock_same_project_headers_node_description= Header files in the same project as the including file
IncludeCategoriesBlock_same_folder_header_node= Headers in Same Folder
IncludeCategoriesBlock_same_folder_header_node_description= Header files in the same folder
IncludeCategoriesBlock_subfolder_header_node= Headers in Subfolders
IncludeCategoriesBlock_subfolder_header_node_description= Header files in subfolders
IncludeCategoriesBlock_system_headers_node= System Headers
IncludeCategoriesBlock_system_headers_node_description= System header files
IncludeCategoriesBlock_system_headers_with_extension_node= System Headers with Extension
IncludeCategoriesBlock_system_headers_with_extension_node_description= System header files with extension, e.g. stdio.h
IncludeCategoriesBlock_system_headers_without_extension_node= System Headers without Extension
IncludeCategoriesBlock_system_headers_without_extension_node_description= System headers without extension, e.g. vector
IncludeCategoriesBlock_unrelated_headers_node= Other Headers
IncludeCategoriesBlock_unrelated_headers_node_description= Header files in the workspace and outside it
IncludeCategoriesBlock_user_defined_categories_node= User-defined Categories
IncludeCategoriesBlock_user_defined_categories_node_description= Categories of header files defined by the user
IncludeCategoriesBlock_header_categories= &Header File Categories
IncludeGroupStyleBlock_keep_includes_together= &Keep include statements together
IncludeGroupStyleBlock_blank_line_before= Separate from previous includes by a &blank line
IncludeGroupStyleBlock_use_relative_path= Use path &relative to the including file
IncludeGroupStyleBlock_use_angle_brackets= Use &angle brackets
IncludeOrderBlock_up= &Up
IncludeOrderBlock_down= D&own
IncludeOrderBlock_order_of_includes= O&rder of Include Statements:
NameStylePreferencePage_title=Name Style
NameStyleBlock_code_node=Code
NameStyleBlock_files_node=Files
@ -457,6 +494,19 @@ NameStyleBlock_invalid_prefix=Invalid prefix
NameStyleBlock_invalid_word_delimiter=Invalid word delimiter
NameStyleBlock_invalid_suffix=Invalid suffix
OrganizeIncludesPreferencePage_title= Organize Includes
OrganizeIncludesBlock_allow_reordering= Allow &reordering of includes
OrganizeIncludesBlock_forward_declare_composite_types= Forward declare &classes, structs and unions
OrganizeIncludesBlock_forward_declare_enums= Forward declare &enums when possible
OrganizeIncludesBlock_forward_declare_functions= Forward declare &functions
OrganizeIncludesBlock_forward_declare_templates= Forward declare &templates
OrganizeIncludesBlock_forward_declare_namespace_elements= Forward declare &namespace elements
OrganizeIncludesBlock_heuristic_header_substitution= Allow &heuristic header file substitution
OrganizeIncludesBlock_unused_statements= &Unused Includes and Forward Declarations:
OrganizeIncludesBlock_comment_out= Comment out
OrganizeIncludesBlock_keep= Keep
OrganizeIncludesBlock_remove= Remove
# edit template dialog
EditTemplateDialog_error_noname=Template name cannot be empty.
EditTemplateDialog_error_invalidName=Template name contains invalid characters.

View file

@ -0,0 +1,152 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import java.util.ArrayList;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.utils.ui.controls.TabFolderLayout;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
/**
* The preference block for configuring styles of names.
*/
public class TabConfigurationBlock extends OptionsConfigurationBlock {
private final OptionsConfigurationBlock[] fTabs;
private final String[] fTabLabels;
private IStatus fStatus = Status.OK_STATUS;
public TabConfigurationBlock(IStatusChangeListener context, IProject project,
OptionsConfigurationBlock[] tabs, String[] tabLabels,
IWorkbenchPreferenceContainer container) {
super(context, project, getAllKeys(tabs), container);
if (tabLabels.length != tabs.length) {
throw new IllegalArgumentException("Number of labels doesn't match the number of tabs"); //$NON-NLS-1$
}
fTabs = tabs;
fTabLabels = tabLabels;
IStatusChangeListener statusMerger = new IStatusChangeListener() {
@Override
public void statusChanged(IStatus status) {
if (status.getSeverity() > fStatus.getSeverity())
fStatus = status;
}
};
for (OptionsConfigurationBlock tab : tabs) {
tab.fContext = statusMerger;
}
}
private static Key[] getAllKeys(OptionsConfigurationBlock[] tabs) {
ArrayList<Key> keys = new ArrayList<Key>();
for (OptionsConfigurationBlock tab : tabs) {
ArrayUtil.addAll(keys, tab.fAllKeys);
}
return keys.toArray(new Key[keys.size()]);
}
@Override
protected Control createContents(Composite parent) {
PixelConverter pixelConverter = new PixelConverter(parent);
final TabFolder folder = new TabFolder(parent, SWT.NONE);
folder.setLayout(new TabFolderLayout());
folder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
for (int i = 0; i < fTabs.length; i++) {
TabItem item = new TabItem(folder, SWT.NONE);
item.setText(fTabLabels[i]);
Composite composite = new Composite(folder, SWT.NONE);
FillLayout layout = new FillLayout();
layout.marginHeight = pixelConverter.convertHorizontalDLUsToPixels(4);
layout.marginWidth = pixelConverter.convertVerticalDLUsToPixels(4);
composite.setLayout(layout);
item.setControl(composite);
item.setData(fTabs[i]);
fTabs[i].createContents(composite);
}
Dialog.applyDialogFont(folder);
folder.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
for (OptionsConfigurationBlock tab : fTabs) {
tab.updateControls();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
return folder;
}
@Override
protected void validateSettings(Key changedKey, String oldValue, String newValue) {
fStatus = Status.OK_STATUS;
for (OptionsConfigurationBlock tab : fTabs) {
tab.validateSettings(changedKey, oldValue, newValue);
if (fStatus.getSeverity() >= IStatus.ERROR)
break;
}
fContext.statusChanged(fStatus);
}
@Override
public boolean performOk() {
for (OptionsConfigurationBlock tab : fTabs) {
tab.performOk();
}
return super.performOk();
}
@Override
public boolean performApply() {
for (OptionsConfigurationBlock tab : fTabs) {
tab.performApply();
}
return super.performApply();
}
@Override
public void performDefaults() {
super.performDefaults();
for (OptionsConfigurationBlock tab : fTabs) {
tab.performDefaults();
}
}
@Override
public void performRevert() {
super.performRevert();
for (OptionsConfigurationBlock tab : fTabs) {
tab.performRevert();
}
}
}

View file

@ -0,0 +1,713 @@
/*******************************************************************************
* Copyright (c) 2012, 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
import java.net.URI;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
public class HeaderSubstitutor {
IncludeMap[] INCLUDE_MAPS = {
cIncludeMap, cIncludeMapWeak, cppIncludeMap, cppIncludeMapWeak,
google3IncludeMap, google3IncludeMapWeak
};
@SuppressWarnings("nls")
private static final IncludeMap symbolIncludeMap = new IncludeMap(false, false, new String[] {
"EOF", "<stdio.h>",
"EOF", "<libio.h>",
"NULL", "<stddef.h>",
"NULL", "<cstddef>",
"NULL", "<cstdio>",
"NULL", "<cstdlib>",
"NULL", "<cstring>",
"NULL", "<ctime>",
"NULL", "<cwchar>",
"NULL", "<locale.h>",
"NULL", "<stdio.h>",
"NULL", "<stdlib.h>",
"NULL", "<string.h>",
"NULL", "<time.h>",
"NULL", "<wchar.h>",
"blkcnt_t", "<sys/stat.h>",
"blkcnt_t", "<sys/types.h>",
"blksize_t", "<sys/types.h>",
"blksize_t", "<sys/stat.h>",
"calloc", "<stdlib.h>",
"daddr_t", "<sys/types.h>",
"daddr_t", "<rpc/types.h>",
"dev_t", "<sys/types.h>",
"dev_t", "<sys/stat.h>",
"error_t", "<errno.h>",
"error_t", "<argp.h>",
"error_t", "<argz.h>",
"free", "<stdlib.h>",
"fsblkcnt_t", "<sys/types.h>",
"fsblkcnt_t", "<sys/statvfs.h>",
"fsfilcnt_t", "<sys/types.h>",
"fsfilcnt_t", "<sys/statvfs.h>",
"gid_t", "<sys/types.h>",
"gid_t", "<grp.h>",
"gid_t", "<pwd.h>",
"gid_t", "<stropts.h>",
"gid_t", "<sys/ipc.h>",
"gid_t", "<sys/stat.h>",
"gid_t", "<unistd.h>",
"id_t", "<sys/types.h>",
"id_t", "<sys/resource.h>",
"ino64_t", "<sys/types.h>",
"ino64_t", "<dirent.h>",
"ino_t", "<sys/types.h>",
"ino_t", "<dirent.h>",
"ino_t", "<sys/stat.h>",
"int8_t", "<sys/types.h>",
"int8_t", "<stdint.h>",
"intptr_t", "<stdint.h>",
"intptr_t", "<unistd.h>",
"key_t", "<sys/types.h>",
"key_t", "<sys/ipc.h>",
"malloc", "<stdlib.h>",
"mode_t", "<sys/types.h>",
"mode_t", "<sys/stat.h>",
"mode_t", "<sys/ipc.h>",
"mode_t", "<sys/mman.h>",
"nlink_t", "<sys/types.h>",
"nlink_t", "<sys/stat.h>",
"off64_t", "<sys/types.h>",
"off64_t", "<unistd.h>",
"off_t", "<sys/types.h>",
"off_t", "<unistd.h>",
"off_t", "<sys/stat.h>",
"off_t", "<sys/mman.h>",
"pid_t", "<sys/types.h>",
"pid_t", "<unistd.h>",
"pid_t", "<signal.h>",
"pid_t", "<sys/msg.h>",
"pid_t", "<sys/shm.h>",
"pid_t", "<termios.h>",
"pid_t", "<time.h>",
"pid_t", "<utmpx.h>",
"realloc", "<stdlib.h>",
"sigset_t", "<signal.h>",
"sigset_t", "<sys/epoll.h>",
"sigset_t", "<sys/select.h>",
"size_t", "<stddef.h>",
"socklen_t", "<bits/socket.h>",
"socklen_t", "<unistd.h>",
"socklen_t", "<arpa/inet.h>",
"ssize_t", "<sys/types.h>",
"ssize_t", "<unistd.h>",
"ssize_t", "<monetary.h>",
"ssize_t", "<sys/msg.h>",
"std::allocator", "<memory>",
"std::allocator", "<string>",
"std::allocator", "<vector>",
"std::allocator", "<map>",
"std::allocator", "<set>",
"std::char_traits", "<string>",
"std::char_traits", "<ostream>",
"std::char_traits", "<istream>",
"suseconds_t", "<sys/types.h>",
"suseconds_t", "<sys/time.h>",
"suseconds_t", "<sys/select.h>",
"u_char", "<sys/types.h>",
"u_char", "<rpc/types.h>",
"uid_t", "<sys/types.h>",
"uid_t", "<unistd.h>",
"uid_t", "<pwd.h>",
"uid_t", "<signal.h>",
"uid_t", "<stropts.h>",
"uid_t", "<sys/ipc.h>",
"uid_t", "<sys/stat.h>",
"useconds_t", "<sys/types.h>",
"useconds_t", "<unistd.h>",
"va_list", "<stdarg.h>",
});
@SuppressWarnings("nls")
private static final IncludeMap cIncludeMap = new IncludeMap(true, false, new String[] {
"<asm/errno-base.h>", "<errno.h>",
"<asm/errno.h>", "<errno.h>",
"<asm/ioctls.h>", "<sys/ioctl.h>",
"<asm/posix_types_32.h>", "<asm/posix_types.h>",
"<asm/posix_types_64.h>", "<asm/posix_types.h>",
"<asm/ptrace-abi.h>", "<asm/ptrace.h>",
"<asm/socket.h>", "<sys/socket.h>",
"<asm/unistd.h>", "<syscall.h>",
"<asm/unistd_32.h>", "<syscall.h>",
"<asm/unistd_64.h>", "<syscall.h>",
"<bits/a.out.h>", "<a.out.h>",
"<bits/byteswap.h>", "<byteswap.h>",
"<bits/cmathcalls.h>", "<complex.h>",
"<bits/confname.h>", "<unistd.h>",
"<bits/dirent.h>", "<dirent.h>",
"<bits/dlfcn.h>", "<dlfcn.h>",
"<bits/elfclass.h>", "<link.h>",
"<bits/endian.h>", "<endian.h>",
"<bits/environments.h>", "<unistd.h>",
"<bits/errno.h>", "<errno.h>",
"<bits/error.h>", "<error.h>",
"<bits/fcntl.h>", "<fcntl.h>",
"<bits/fcntl2.h>", "<fcntl.h>",
"<bits/fenv.h>", "<fenv.h>",
"<bits/fenvinline.h>", "<fenv.h>",
"<bits/huge_val.h>", "<math.h>",
"<bits/huge_valf.h>", "<math.h>",
"<bits/huge_vall.h>", "<math.h>",
"<bits/in.h>", "<netinet/in.h>",
"<bits/inf.h>", "<math.h>",
"<bits/ioctl-types.h>", "<sys/ioctl.h>",
"<bits/ioctls.h>", "<sys/ioctl.h>",
"<bits/ipc.h>", "<sys/ipc.h>",
"<bits/ipctypes.h>", "<sys/ipc.h>",
"<bits/libio-ldbl.h>", "<libio.h>",
"<bits/link.h>", "<link.h>",
"<bits/locale.h>", "<locale.h>",
"<bits/mathcalls.h>", "<math.h>",
"<bits/mathdef.h>", "<math.h>",
"<bits/mathinline.h>", "<math.h>",
"<bits/mman.h>", "<sys/mman.h>",
"<bits/monetary-ldbl.h>", "<monetary.h>",
"<bits/mqueue.h>", "<mqueue.h>",
"<bits/mqueue2.h>", "<mqueue.h>",
"<bits/msq.h>", "<sys/msg.h>",
"<bits/nan.h>", "<math.h>",
"<bits/netdb.h>", "<netdb.h>",
"<bits/poll.h>", "<poll.h>",
"<bits/posix1_lim.h>", "<limits.h>",
"<bits/posix2_lim.h>", "<limits.h>",
"<bits/posix_opt.h>", "<unistd.h>",
"<bits/predefs.h>", "<features.h>",
"<bits/printf-ldbl.h>", "<printf.h>",
"<bits/pthreadtypes.h>", "<pthread.h>",
"<bits/resource.h>", "<sys/resource.h>",
"<bits/sched.h>", "<sched.h>",
"<bits/select.h>", "<sys/select.h>",
"<bits/sem.h>", "<sys/sem.h>",
"<bits/semaphore.h>", "<semaphore.h>",
"<bits/setjmp.h>", "<setjmp.h>",
"<bits/shm.h>", "<sys/shm.h>",
"<bits/sigaction.h>", "<signal.h>",
"<bits/sigcontext.h>", "<signal.h>",
"<bits/siginfo.h>", "<signal.h>",
"<bits/signum.h>", "<signal.h>",
"<bits/sigset.h>", "<signal.h>",
"<bits/sigstack.h>", "<signal.h>",
"<bits/sigthread.h>", "<signal.h>",
"<bits/sockaddr.h>", "<sys/un.h>",
"<bits/socket.h>", "<sys/socket.h>",
"<bits/stab.def>", "<stab.h>",
"<bits/stat.h>", "<sys/stat.h>",
"<bits/statfs.h>", "<sys/statfs.h>",
"<bits/statvfs.h>", "<sys/statvfs.h>",
"<bits/stdio-ldbl.h>", "<stdio.h>",
"<bits/stdio-lock.h>", "<libio.h>",
"<bits/stdio.h>", "<stdio.h>",
"<bits/stdio2.h>", "<stdio.h>",
"<bits/stdio_lim.h>", "<stdio.h>",
"<bits/stdlib-ldbl.h>", "<stdlib.h>",
"<bits/stdlib.h>", "<stdlib.h>",
"<bits/string.h>", "<string.h>",
"<bits/string2.h>", "<string.h>",
"<bits/string3.h>", "<string.h>",
"<bits/stropts.h>", "<stropts.h>",
"<bits/sys_errlist.h>", "<stdio.h>",
"<bits/syscall.h>", "<syscall.h>",
"<bits/syslog-ldbl.h>", "<syslog.h>",
"<bits/syslog-path.h>", "<syslog.h>",
"<bits/syslog.h>", "<syslog.h>",
"<bits/termios.h>", "<termios.h>",
"<bits/time.h>", "<sys/time.h>",
"<bits/types.h>", "<sys/types.h>",
"<bits/uio.h>", "<sys/uio.h>",
"<bits/unistd.h>", "<unistd.h>",
"<bits/ustat.h>", "<ustat.h>",
"<bits/utmp.h>", "<utmp.h>",
"<bits/utmpx.h>", "<utmpx.h>",
"<bits/utsname.h>", "<sys/utsname.h>",
"<bits/waitflags.h>", "<sys/wait.h>",
"<bits/waitstatus.h>", "<sys/wait.h>",
"<bits/wchar-ldbl.h>", "<wchar.h>",
"<bits/wchar.h>", "<wchar.h>",
"<bits/wchar2.h>", "<wchar.h>",
"<bits/xopen_lim.h>", "<limits.h>",
"<bits/xtitypes.h>", "<stropts.h>",
"<linux/errno.h>", "<errno.h>",
"<linux/limits.h>", "<limits.h>",
"<linux/socket.h>", "<sys/socket.h>",
"<sys/poll.h>", "<poll.h>",
"<sys/syscall.h>", "<syscall.h>",
"<sys/syslog.h>", "<syslog.h>",
"<sys/ucontext.h>", "<ucontext.h>",
"<sys/ustat.h>", "<ustat.h>",
"<wait.h>", "<sys/wait.h>",
});
private static final IncludeMap cIncludeMapWeak = new IncludeMap(false, false, new String[] {
});
@SuppressWarnings("nls")
private static final IncludeMap cppIncludeMap = new IncludeMap(true, true, new String[] {
"<auto_ptr.h>", "<memory>",
"<backward/auto_ptr.h>", "<memory>",
"<backward/binders.h>", "<functional>",
"<backward/hash_fun.h>", "<hash_map>",
"<backward/hash_fun.h>", "<hash_set>",
"<backward/hashtable.h>", "<hash_map>",
"<backward/hashtable.h>", "<hash_set>",
"<backward/strstream>", "<strstream>",
"<binders.h>", "<functional>",
"<bits/algorithmfwd.h>", "<algorithm>",
"<bits/allocator.h>", "<memory>",
"<bits/atomic_word.h>", "<ext/atomicity.h>",
"<bits/basic_file.h>", "<fstream>",
"<bits/basic_ios.h>", "<ios>",
"<bits/basic_string.h>", "<string>",
"<bits/basic_string.tcc>", "<string>",
"<bits/boost_concept_check.h>", "<bits/concept_check.h>",
"<bits/boost_sp_shared_count.h>", "<memory>",
"<bits/c++allocator.h>", "<memory>",
"<bits/c++config.h>", "<cstddef>",
"<bits/c++io.h>", "<ext/stdio_sync_filebuf.h>",
"<bits/char_traits.h>", "<string>",
"<bits/cmath.tcc>", "<cmath>",
"<bits/codecvt.h>", "<fstream>",
"<bits/codecvt.h>", "<locale>",
"<bits/ctype_base.h>", "<locale>",
"<bits/ctype_base.h>", "<ios>",
"<bits/ctype_inline.h>", "<locale>",
"<bits/ctype_inline.h>", "<ios>",
"<bits/cxxabi_tweaks.h>", "<cxxabi.h>",
"<bits/deque.tcc>", "<deque>",
"<bits/exception_defines.h>", "<exception>",
"<bits/fstream.tcc>", "<fstream>",
"<bits/functexcept.h>", "<algorithm>",
"<bits/functional_hash.h>", "<unordered_map>",
"<bits/gslice.h>", "<valarray>",
"<bits/gslice_array.h>", "<valarray>",
"<bits/hashtable.h>", "<unordered_map>",
"<bits/hashtable.h>", "<unordered_set>",
"<bits/indirect_array.h>", "<valarray>",
"<bits/ios_base.h>", "<iostream>",
"<bits/ios_base.h>", "<ios>",
"<bits/ios_base.h>", "<iomanip>",
"<bits/istream.tcc>", "<istream>",
"<bits/list.tcc>", "<list>",
"<bits/locale_classes.h>", "<locale>",
"<bits/locale_classes.h>", "<ios>",
"<bits/locale_classes.tcc>", "<locale>",
"<bits/locale_classes.tcc>", "<ios>",
"<bits/locale_facets.h>", "<locale>",
"<bits/locale_facets.h>", "<ios>",
"<bits/locale_facets.tcc>", "<locale>",
"<bits/locale_facets.tcc>", "<ios>",
"<bits/locale_facets_nonio.h>", "<locale>",
"<bits/locale_facets_nonio.tcc>", "<locale>",
"<bits/localefwd.h>", "<locale>",
"<bits/mask_array.h>", "<valarray>",
"<bits/messages_members.h>", "<locale>",
"<bits/move.h>", "<algorithm>",
"<bits/ostream.tcc>", "<ostream>",
"<bits/ostream_insert.h>", "<ostream>",
"<bits/postypes.h>", "<iostream>",
"<bits/postypes.h>", "<string>",
"<bits/slice_array.h>", "<valarray>",
"<bits/sstream.tcc>", "<sstream>",
"<bits/stl_algo.h>", "<algorithm>",
"<bits/stl_algobase.h>", "<algorithm>",
"<bits/stl_bvector.h>", "<vector>",
"<bits/stl_construct.h>", "<memory>",
"<bits/stl_deque.h>", "<deque>",
"<bits/stl_function.h>", "<functional>",
"<bits/stl_heap.h>", "<queue>",
"<bits/stl_iterator.h>", "<iterator>",
"<bits/stl_iterator_base_funcs.h>", "<iterator>",
"<bits/stl_iterator_base_types.h>", "<iterator>",
"<bits/stl_list.h>", "<list>",
"<bits/stl_map.h>", "<map>",
"<bits/stl_move.h>", "<algorithm>",
"<bits/stl_multimap.h>", "<map>",
"<bits/stl_multiset.h>", "<set>",
"<bits/stl_numeric.h>", "<numeric>",
"<bits/stl_pair.h>", "<utility>",
"<bits/stl_pair.h>", "<tr1/utility>",
"<bits/stl_queue.h>", "<queue>",
"<bits/stl_raw_storage_iter.h>", "<memory>",
"<bits/stl_relops.h>", "<utility>",
"<bits/stl_set.h>", "<set>",
"<bits/stl_stack.h>", "<stack>",
"<bits/stl_tempbuf.h>", "<memory>",
"<bits/stl_tree.h>", "<map>",
"<bits/stl_tree.h>", "<set>",
"<bits/stl_uninitialized.h>", "<memory>",
"<bits/stl_vector.h>", "<vector>",
"<bits/stream_iterator.h>", "<iterator>",
"<bits/streambuf.tcc>", "<streambuf>",
"<bits/streambuf_iterator.h>", "<iterator>",
"<bits/streambuf_iterator.h>", "<ios>",
"<bits/stringfwd.h>", "<string>",
"<bits/valarray_after.h>", "<valarray>",
"<bits/valarray_array.h>", "<valarray>",
"<bits/valarray_array.tcc>", "<valarray>",
"<bits/valarray_before.h>", "<valarray>",
"<bits/vector.tcc>", "<vector>",
"<debug/safe_iterator.tcc>", "<debug/safe_iterator.h>",
"<exception_defines.h>", "<exception>",
"<ext/algorithm>", "<algorithm>",
"<ext/functional>", "<functional>",
"<ext/hash_map>", "<hash_map>",
"<ext/hash_set>", "<hash_set>",
"<ext/numeric>", "<numeric>",
"<ext/slist>", "<slist>",
"<ext/sso_string_base.h>", "<string>",
"<ext/vstring.h>", "<string>",
"<ext/vstring.tcc>", "<string>",
"<ext/vstring_fwd.h>", "<string>",
"<hash_fun.h>", "<hash_map>",
"<hash_fun.h>", "<hash_set>",
"<hashtable.h>", "<hash_map>",
"<hashtable.h>", "<hash_set>",
"<tr1/bessel_function.tcc>", "<tr1/cmath>",
"<tr1/beta_function.tcc>", "<tr1/cmath>",
"<tr1/ell_integral.tcc>", "<tr1/cmath>",
"<tr1/exp_integral.tcc>", "<tr1/cmath>",
"<tr1/gamma.tcc>", "<tr1/cmath>",
"<tr1/hypergeometric.tcc>", "<tr1/cmath>",
"<tr1/legendre_function.tcc>", "<tr1/cmath>",
"<tr1/modified_bessel_func.tcc>", "<tr1/cmath>",
"<tr1/poly_hermite.tcc>", "<tr1/cmath>",
"<tr1/poly_laguerre.tcc>", "<tr1/cmath>",
"<tr1/riemann_zeta.tcc>", "<tr1/cmath>",
"<tr1_impl/array>", "<array>",
"<tr1_impl/array>", "<tr1/array>",
"<tr1_impl/boost_shared_ptr.h>", "<memory>",
"<tr1_impl/boost_shared_ptr.h>", "<tr1/memory>",
"<tr1_impl/boost_sp_counted_base.h>", "<memory>",
"<tr1_impl/boost_sp_counted_base.h>", "<tr1/memory>",
"<tr1_impl/cctype>", "<cctype>",
"<tr1_impl/cctype>", "<tr1/cctype>",
"<tr1_impl/cfenv>", "<cfenv>",
"<tr1_impl/cfenv>", "<tr1/cfenv>",
"<tr1_impl/cinttypes>", "<cinttypes>",
"<tr1_impl/cinttypes>", "<tr1/cinttypes>",
"<tr1_impl/cmath>", "<cmath>",
"<tr1_impl/cmath>", "<tr1/cmath>",
"<tr1_impl/complex>", "<complex>",
"<tr1_impl/complex>", "<tr1/complex>",
"<tr1_impl/cstdint>", "<cstdint>",
"<tr1_impl/cstdint>", "<tr1/cstdint>",
"<tr1_impl/cstdio>", "<cstdio>",
"<tr1_impl/cstdio>", "<tr1/cstdio>",
"<tr1_impl/cstdlib>", "<cstdlib>",
"<tr1_impl/cstdlib>", "<tr1/cstdlib>",
"<tr1_impl/cwchar>", "<cwchar>",
"<tr1_impl/cwchar>", "<tr1/cwchar>",
"<tr1_impl/cwctype>", "<cwctype>",
"<tr1_impl/cwctype>", "<tr1/cwctype>",
"<tr1_impl/functional>", "<functional>",
"<tr1_impl/functional>", "<tr1/functional>",
"<tr1_impl/functional_hash.h>", "<tr1/functional_hash.h>",
"<tr1_impl/hashtable>", "<tr1/hashtable.h>",
"<tr1_impl/random.tcc>", "<random>",
"<tr1_impl/random.tcc>", "<tr1/random>",
"<tr1_impl/random>", "<random>",
"<tr1_impl/random>", "<tr1/random>",
"<tr1_impl/regex>", "<regex>",
"<tr1_impl/regex>", "<tr1/regex>",
"<tr1_impl/type_traits>", "<tr1/type_traits>",
"<tr1_impl/type_traits>", "<type_traits>",
"<tr1_impl/unordered_map>", "<tr1/unordered_map>",
"<tr1_impl/unordered_map>", "<unordered_map>",
"<tr1_impl/unordered_set>", "<tr1/unordered_set>",
"<tr1_impl/unordered_set>", "<unordered_set>",
"<tr1_impl/utility>", "<tr1/utility>",
"<tr1_impl/utility>", "<utility>",
});
@SuppressWarnings("nls")
private static final IncludeMap cppIncludeMapWeak = new IncludeMap(false, true, new String[] {
"<assert.h>", "<cassert>",
"<complex.h>", "<ccomplex>",
"<ctype.h>", "<cctype>",
"<errno.h>", "<cerrno>",
"<fenv.h>", "<cfenv>",
"<float.h>", "<cfloat>",
"<inttypes.h>", "<cinttypes>",
"<iso646.h>", "<ciso646>",
"<limits.h>", "<climits>",
"<locale.h>", "<clocale>",
"<math.h>", "<cmath>",
"<setjmp.h>", "<csetjmp>",
"<signal.h>", "<csignal>",
"<stdarg.h>", "<cstdarg>",
"<stdbool.h>", "<cstdbool>",
"<stddef.h>", "<cstddef>",
"<stdint.h>", "<cstdint>",
"<stdio.h>", "<cstdio>",
"<stdlib.h>", "<cstdlib>",
"<string.h>", "<cstring>",
"<tgmath.h>", "<ctgmath>",
"<time.h>", "<ctime>",
"<wchar.h>", "<cwchar>",
"<wctype.h>", "<cwctype>",
"<ios>", "<istream>",
"<ios>", "<ostream>",
"<iosfwd>", "<ios>",
"<iosfwd>", "<streambuf>",
"<istream>", "<fstream>",
"<istream>", "<iostream>",
"<istream>", "<sstream>",
"<ostream>", "<fstream>",
"<ostream>", "<iostream>",
"<ostream>", "<istream>",
"<ostream>", "<sstream>",
"<streambuf>", "<ios>",
});
@SuppressWarnings("nls")
private static final IncludeMap google3IncludeMap = new IncludeMap(true, true, new String[] {
"<ios>", "base/logging.h",
"<ios>", "base/logging.h",
"<iosfwd>", "base/logging.h",
"<iosfwd>", "base/logging.h",
"<istream>", "base/logging.h",
"<istream>", "base/logging.h",
"<istream>", "base/logging.h",
"<ostream>", "base/logging.h",
"<ostream>", "base/logging.h",
"<ostream>", "base/logging.h",
"<ostream>", "base/logging.h",
"<streambuf>", "base/logging.h",
"base/vlog_is_on.h", "base/logging.h"
});
@SuppressWarnings("nls")
private static final IncludeMap google3IncludeMapWeak = new IncludeMap(false, true, new String[] {
"base/commandlineflags_declare.h", "base/commandlineflags.h"
});
private final InclusionContext fContext;
private List<IncludeMap> fIncludeMaps;
public HeaderSubstitutor(InclusionContext context) {
fContext = context;
}
/**
* Selects the header file to be appear in the {@code #include} statement given the header file
* that needs to be included. Returns absolute path for the header if it can be uniquely
* determined, or {@code null} otherwise. The header is determined uniquely if there are no
* optional replacement headers for it, and there are no more that one forced replacement.
* @param path absolute path of the header to be included directly or indirectly
* @return absolute path of the header to be included directly
*/
public IPath getUniqueRepresentativeHeader(IPath path) {
IncludeInfo includeInfo = fContext.getIncludeForHeaderFile(path);
if (includeInfo == null)
return null;
List<IncludeMap> maps = getAllIncludeMaps();
for (IncludeMap map : maps) {
if (map.isForcedReplacement()) {
List<IncludeInfo> replacements = map.getMapping(includeInfo);
if (replacements.size() == 1) {
includeInfo = replacements.get(0);
} else if (replacements.size() > 1) {
return null;
}
}
}
for (IncludeMap map : maps) {
if (!map.isForcedReplacement()) {
if (!map.getMapping(includeInfo).isEmpty()) {
return null;
}
}
}
return fContext.resolveInclude(includeInfo);
}
public IPath getPreferredRepresentativeHeader(IPath path) {
IncludeInfo includeInfo = fContext.getIncludeForHeaderFile(path);
if (includeInfo == null)
return path;
// TODO(sprigogin): Take symbolIncludeMap into account.
List<IncludeInfo> candidates = new ArrayList<IncludeInfo>();
candidates.add(includeInfo);
List<IncludeMap> maps = getAllIncludeMaps();
for (IncludeMap map : maps) {
for (int i = 0; i < candidates.size();) {
IncludeInfo candidate = candidates.get(i);
List<IncludeInfo> replacements = map.getMapping(candidate);
int increment = 1;
if (!replacements.isEmpty()) {
if (map.isForcedReplacement()) {
candidates.remove(i);
increment = 0;
}
candidates.addAll(i, replacements);
increment += replacements.size();
}
i += increment;
}
}
IPath firstResolved = null;
for (IncludeInfo candidate : candidates) {
IPath header = fContext.resolveInclude(candidate);
if (header != null) {
if (fContext.isIncluded(header))
return header;
if (firstResolved == null)
firstResolved = header;
}
}
return firstResolved != null ? firstResolved : path;
}
/**
* Performs heuristic header substitution.
*/
public IPath getPreferredRepresentativeHeaderByHeuristic(InclusionRequest request) {
Set<IIndexFile> indexFiles = request.getDeclaringFiles().keySet();
String symbolName = request.getBinding().getName();
ArrayDeque<IIndexFile> front = new ArrayDeque<IIndexFile>();
HashSet<IIndexFile> processed = new HashSet<IIndexFile>();
try {
// Look for headers without an extension and a matching name.
if (fContext.isCXXLanguage()) {
front.addAll(indexFiles);
processed.addAll(indexFiles);
while (!front.isEmpty()) {
IIndexFile file = front.remove();
String path = IncludeUtil.getPath(file);
if (!hasExtension(path) && getFilename(path).equalsIgnoreCase(symbolName)) {
// A C++ header without an extension and with a name which matches the name
// of the symbol which should be declared is a perfect candidate for inclusion.
return IndexLocationFactory.getAbsolutePath(file.getLocation());
}
// Process the next level of the include hierarchy.
IIndexInclude[] includes = fContext.getIndex().findIncludedBy(file, 0);
for (IIndexInclude include : includes) {
IIndexFile includer = include.getIncludedBy();
if (!processed.contains(includer)) {
front.add(includer);
processed.add(includer);
}
}
}
}
// Repeat the process, this time only looking for headers without an extension.
front.clear();
front.addAll(indexFiles);
processed.clear();
processed.addAll(indexFiles);
while (!front.isEmpty()) {
IIndexFile file = front.remove();
String path = IncludeUtil.getPath(file);
if (fContext.isCXXLanguage() && !hasExtension(path)) {
// A C++ header without an extension is still a very good candidate for inclusion.
return IndexLocationFactory.getAbsolutePath(file.getLocation());
}
// Process the next level of the include hierarchy.
IIndexInclude[] includes = fContext.getIndex().findIncludedBy(file, 0);
for (IIndexInclude include : includes) {
IIndexFile includer = include.getIncludedBy();
if (!processed.contains(includer)) {
URI uri = includer.getLocation().getURI();
if (IncludeUtil.isSource(includer, fContext.getProject()) || isWorkspaceFile(uri)) {
return IndexLocationFactory.getAbsolutePath(file.getLocation());
}
front.add(includer);
processed.add(includer);
}
}
}
} catch (CoreException e) {
CUIPlugin.log(e);
}
return request.getCandidatePaths().iterator().next();
}
private List<IncludeMap> getAllIncludeMaps() {
if (fIncludeMaps == null) {
fIncludeMaps = new ArrayList<IncludeMap>();
for (IncludeMap map : INCLUDE_MAPS) {
if (fContext.isCXXLanguage() || !map.isCppOnly())
fIncludeMaps.add(map);
}
}
return fIncludeMaps;
}
/**
* Returns whether the given URI is an URI within the workspace
* @param uri
* @return
*/
private static boolean isWorkspaceFile(URI uri) {
for (IFile file : ResourceLookup.findFilesForLocationURI(uri)) {
if (file.exists()) {
return true;
}
}
return false;
}
/**
* Returns whether the given path has a file suffix, or not.
* @param path
* @return
*/
private static boolean hasExtension(String path) {
return path.indexOf('.', path.lastIndexOf('/') + 1) >= 0;
}
/**
* Returns the filename of the given path, without extension.
* @param path
* @return
*/
private static String getFilename(String path) {
int startPos = path.lastIndexOf('/') + 1;
int endPos = path.lastIndexOf('.');
if (endPos > startPos) {
return path.substring(startPos, endPos);
} else {
return path.substring(startPos);
}
}
}

View file

@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
import java.util.Collection;
import org.eclipse.core.runtime.IPath;
/**
* Interface for selecting one of alternative headers.
*/
public interface IHeaderChooser {
/**
* Chooses one header out of multiple alternatives.
*
* @param bindingName the name of the binding for which the header is selected
* @param headers absolute file system locations of the headers defining the binding
* @return the chosen header or {@code null} if nothing was selected
*/
public IPath chooseHeader(String bindingName, Collection<IPath> headers);
}

View file

@ -0,0 +1,265 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.preferences.PreferencesMessages;
/**
* Style preferences for a category of include statements.
*/
public class IncludeGroupStyle implements Comparable<IncludeGroupStyle> {
public enum IncludeKind {
RELATED(PreferencesMessages.IncludeCategoriesBlock_related_headers_node,
PreferencesMessages.IncludeCategoriesBlock_related_headers_node_description,
null),
PARTNER(PreferencesMessages.IncludeCategoriesBlock_partner_header_node,
PreferencesMessages.IncludeCategoriesBlock_partner_header_node_description,
RELATED),
IN_SAME_FOLDER(PreferencesMessages.IncludeCategoriesBlock_same_folder_header_node,
PreferencesMessages.IncludeCategoriesBlock_same_folder_header_node_description,
RELATED),
IN_SUBFOLDER(PreferencesMessages.IncludeCategoriesBlock_subfolder_header_node,
PreferencesMessages.IncludeCategoriesBlock_subfolder_header_node_description,
RELATED),
SYSTEM(PreferencesMessages.IncludeCategoriesBlock_system_headers_node,
PreferencesMessages.IncludeCategoriesBlock_system_headers_node_description,
null),
SYSTEM_WITH_EXTENSION(PreferencesMessages.IncludeCategoriesBlock_system_headers_with_extension_node,
PreferencesMessages.IncludeCategoriesBlock_system_headers_with_extension_node_description,
SYSTEM),
SYSTEM_WITHOUT_EXTENSION(PreferencesMessages.IncludeCategoriesBlock_system_headers_without_extension_node,
PreferencesMessages.IncludeCategoriesBlock_system_headers_without_extension_node_description,
SYSTEM),
OTHER(PreferencesMessages.IncludeCategoriesBlock_unrelated_headers_node,
PreferencesMessages.IncludeCategoriesBlock_unrelated_headers_node_description,
null),
IN_SAME_PROJECT(PreferencesMessages.IncludeCategoriesBlock_same_project_headers_node,
PreferencesMessages.IncludeCategoriesBlock_same_project_headers_node_description,
OTHER),
IN_OTHER_PROJECT(PreferencesMessages.IncludeCategoriesBlock_other_project_headers_node,
PreferencesMessages.IncludeCategoriesBlock_other_project_headers_node_description,
OTHER),
EXTERNAL(PreferencesMessages.IncludeCategoriesBlock_external_headers_node,
PreferencesMessages.IncludeCategoriesBlock_external_headers_node_description,
OTHER),
MATCHING_PATTERN(PreferencesMessages.IncludeCategoriesBlock_user_defined_categories_node,
PreferencesMessages.IncludeCategoriesBlock_user_defined_categories_node_description,
null);
public final String name;
public final String description;
public final IncludeKind parent;
public final List<IncludeKind> children = new ArrayList<IncludeKind>();
private IncludeKind(String name, String description, IncludeKind parent) {
this.name = name;
this.description = description;
this.parent = parent;
if (parent != null)
parent.children.add(this);
}
public boolean hasChildren() {
return !children.isEmpty();
}
}
private static final String TAG_STYLE = "style"; //$NON-NLS-1$
private static final String TAG_NAME = "name"; //$NON-NLS-1$
private static final String TAG_PATTERN = "pattern"; //$NON-NLS-1$
private static final String TAG_KEEP_TOGETHER = "keep_together"; //$NON-NLS-1$
private static final String TAG_BLANK_LINE_BEFORE = "blank_line_before"; //$NON-NLS-1$
private static final String TAG_RELATIVE_PATH = "relative_path"; //$NON-NLS-1$
private static final String TAG_ANGLE_BRACKETS = "angle_brackets"; //$NON-NLS-1$
private static final String TAG_ORDER = "order"; //$NON-NLS-1$
private final IncludeKind includeKind;
private boolean keepTogether;
private boolean blankLineBefore;
private boolean relativePath;
private boolean angleBrackets;
private Pattern headerNamePattern;
private String name;
private int order; // Relative position of the include group. Ignored if keepTogether is false.
public IncludeGroupStyle(IncludeKind includeKind) {
if (includeKind == null || includeKind == IncludeKind.MATCHING_PATTERN)
throw new IllegalArgumentException();
this.includeKind = includeKind;
}
public IncludeGroupStyle(String name, Pattern headerNamePattern) {
if (name == null)
throw new IllegalArgumentException();
if (headerNamePattern == null)
throw new IllegalArgumentException();
this.includeKind = IncludeKind.MATCHING_PATTERN;
this.name = name;
this.headerNamePattern = headerNamePattern;
}
public boolean isKeepTogether() {
return keepTogether;
}
public void setKeepTogether(boolean value) {
this.keepTogether = value;
}
public boolean isBlankLineBefore() {
return blankLineBefore;
}
public void setBlankLineBefore(boolean value) {
this.blankLineBefore = value;
}
public boolean isRelativePath() {
return relativePath;
}
public void setRelativePath(boolean value) {
assert !includeKind.hasChildren();
this.relativePath = value;
}
public boolean isAngleBrackets() {
return angleBrackets;
}
public void setAngleBrackets(boolean value) {
assert !includeKind.hasChildren();
this.angleBrackets = value;
}
public Pattern getHeaderNamePattern() {
return headerNamePattern;
}
public void setHeaderNamePattern(Pattern headerNamePattern) {
this.headerNamePattern = headerNamePattern;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public IncludeKind getIncludeKind() {
return includeKind;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public static IncludeGroupStyle fromMemento(IMemento memento, IncludeKind includeKind) {
IncludeGroupStyle style;
if (includeKind == IncludeKind.MATCHING_PATTERN) {
String name = nullToEmpty(memento.getString(TAG_NAME));
String pattern = nullToEmpty(memento.getString(TAG_PATTERN));
style = new IncludeGroupStyle(name, Pattern.compile(pattern));
} else {
style = new IncludeGroupStyle(includeKind);
}
style.setKeepTogether(nullToFalse(memento.getBoolean(TAG_KEEP_TOGETHER)));
style.setBlankLineBefore(nullToFalse(memento.getBoolean(TAG_BLANK_LINE_BEFORE)));
if (!includeKind.hasChildren()) {
style.setRelativePath(nullToFalse(memento.getBoolean(TAG_RELATIVE_PATH)));
style.setAngleBrackets(nullToFalse(memento.getBoolean(TAG_ANGLE_BRACKETS)));
}
Integer order = memento.getInteger(TAG_ORDER);
if (order != null)
style.setOrder(order.intValue());
return style;
}
private static boolean nullToFalse(Boolean val) {
return val != null && val.booleanValue();
}
private static String nullToEmpty(String val) {
return val != null ? val : ""; //$NON-NLS-1$
}
public void saveToMemento(IMemento memento) {
if (includeKind == IncludeKind.MATCHING_PATTERN) {
memento.putString(TAG_NAME, name);
memento.putString(TAG_PATTERN, headerNamePattern.toString());
}
memento.putBoolean(TAG_KEEP_TOGETHER, keepTogether);
memento.putBoolean(TAG_BLANK_LINE_BEFORE, blankLineBefore);
if (!includeKind.hasChildren()) {
memento.putBoolean(TAG_RELATIVE_PATH, relativePath);
memento.putBoolean(TAG_ANGLE_BRACKETS, angleBrackets);
}
if (keepTogether)
memento.putInteger(TAG_ORDER, order);
}
@Override
public String toString() {
XMLMemento memento = XMLMemento.createWriteRoot(TAG_STYLE);
saveToMemento(memento);
StringWriter writer = new StringWriter();
try {
memento.save(writer);
} catch (IOException e) {
CUIPlugin.log(e);
}
return writer.toString();
}
public static IncludeGroupStyle fromString(String str, IncludeKind includeKind) {
StringReader reader = new StringReader(str);
XMLMemento memento;
try {
memento = XMLMemento.createReadRoot(reader);
} catch (WorkbenchException e) {
return null;
}
return fromMemento(memento, includeKind);
}
/**
* Compares styles according to their sorting order.
*/
@Override
public int compareTo(IncludeGroupStyle other) {
if (keepTogether != other.keepTogether)
return keepTogether ? -1 : 1;
int c = order - other.order;
if (c != 0)
return c;
return includeKind.ordinal() - other.includeKind.ordinal();
}
}

View file

@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (c) 2012, 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
public class IncludeInfo {
private final String name;
private final boolean isSystem;
public IncludeInfo(String name, boolean isSystem) {
if (name == null || name.isEmpty())
throw new IllegalArgumentException();
this.name = name;
this.isSystem = isSystem;
}
public IncludeInfo(String includeText) {
if (includeText == null || includeText.isEmpty())
throw new IllegalArgumentException();
boolean isSystem = false;
int begin = 0;
switch (includeText.charAt(0)) {
case '<':
isSystem = true;
//$FALL-THROUGH$
case '"':
++begin;
break;
}
int end = includeText.length();
switch (includeText.charAt(end - 1)) {
case '>':
case '"':
--end;
break;
}
if (begin >= end)
throw new IllegalArgumentException();
this.name = includeText.substring(begin, end);
this.isSystem = isSystem;
}
/**
* Returns the part of the include statement identifying the included header file without
* quotes or angle brackets.
*/
public final String getName() {
return name;
}
public final boolean isSystem() {
return isSystem;
}
@Override
public int hashCode() {
return name.hashCode() * 31 + (isSystem ? 1 : 0);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IncludeInfo other = (IncludeInfo) obj;
return name.equals(other.name) && isSystem == other.isSystem;
}
/**
* Returns the include string as it appears in an {@code #include} statement.
*/
@Override
public String toString() {
return (isSystem ? '<' : '"') + name + (isSystem ? '>' : '"');
}
}

View file

@ -0,0 +1,116 @@
/*******************************************************************************
* Copyright (c) 2012, 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class IncludeMap {
private final boolean forcedReplacement;
private final Map<IncludeInfo, List<IncludeInfo>> map;
private final boolean cppOnly;
public IncludeMap(boolean forcedReplacement, boolean cppOnly) {
this.forcedReplacement = forcedReplacement;
this.cppOnly = cppOnly;
this.map = new HashMap<IncludeInfo, List<IncludeInfo>>();
}
/**
* @param keysAndValues an array of keys and values: [key1, value1, key2, value2, ...].
* Keys and values may be optionally surrounded by double quotes or angle brackets.
* Angle brackets indicate a system include.
*/
public IncludeMap(boolean forcedReplacement, boolean cppOnly, String[] keysAndValues) {
if (keysAndValues.length % 2 != 0)
throw new IllegalArgumentException("More keys than values"); //$NON-NLS-1$
this.forcedReplacement = forcedReplacement;
this.cppOnly = cppOnly;
this.map = new HashMap<IncludeInfo, List<IncludeInfo>>(keysAndValues.length / 2);
for (int i = 0; i < keysAndValues.length;) {
String key = keysAndValues[i++];
addMapping(key, keysAndValues[i++]);
}
}
/**
* Indicates that header file {@code to} should be used instead of {@code from}.
*
* @param from The header file to be replaced.
* @param to The header file to be used.
*/
protected void addMapping(IncludeInfo from, IncludeInfo to) {
List<IncludeInfo> list = map.get(from);
if (list == null) {
list = new ArrayList<IncludeInfo>(2);
map.put(from, list);
}
list.add(to);
}
/**
* Indicates that header file {@code to} should be used instead of {@code from}.
* @param from The header file to be replaced. The header is represented by an include name
* optionally surrounded by double quotes or angle brackets. Angle brackets indicate
* a system include.
* @param to The header file to be used. The header is represented by an include name optionally
* surrounded by double quotes or angle brackets. Angle brackets indicate a system include.
*/
public void addMapping(String from, String to) {
addMapping(new IncludeInfo(from), new IncludeInfo(to));
}
/**
* Returns header files that should be used instead of the given one.
*
* @param from The header file to be replaced. A system header has to match exactly.
* A non-system header matches both, non-system and system headers.
* @return The list of header files ordered by decreasing preference.
*/
public List<IncludeInfo> getMapping(IncludeInfo from) {
List<IncludeInfo> list = map.get(from);
if (list == null) {
if (!from.isSystem())
list = map.get(new IncludeInfo(from.getName(), true));
if (list == null)
return Collections.emptyList();
}
return list;
}
/**
* Returns header files that should be used instead of the given one.
*
* @param from The header file to be replaced. A system header has to match exactly.
* A non-system header matches both, non-system and system headers.
* @return The list of header files ordered by decreasing preference.
*/
public List<IncludeInfo> getMapping(String from) {
return getMapping(new IncludeInfo(from));
}
public IncludeInfo getPreferredMapping(IncludeInfo from) {
List<IncludeInfo> list = getMapping(from);
return list == null ? null : list.get(0);
}
public boolean isForcedReplacement() {
return forcedReplacement;
}
public boolean isCppOnly() {
return cppOnly;
}
}

View file

@ -0,0 +1,169 @@
/*******************************************************************************
* Copyright (c) 2012, 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle.IncludeKind;
/**
* Preferences for managing of includes.
*/
public class IncludePreferences {
private static final String DEFAULT_PARTNER_FILE_SUFFIXES = "test,unittest"; //$NON-NLS-1$
public static enum UnusedStatementDisposition { REMOVE, COMMENT_OUT, KEEP }
public final Map<IncludeKind, IncludeGroupStyle> includeStyles;
public final boolean allowReordering;
public final boolean heuristicHeaderSubstitution;
public final boolean allowPartnerIndirectInclusion;
public final boolean forwardDeclareCompositeTypes;
public final boolean forwardDeclareEnums;
public final boolean forwardDeclareFunctions;
// TODO(sprigogin): Create a preference.
public final boolean forwardDeclareExternalVariables = false;
public final boolean forwardDeclareTemplates;
public final boolean forwardDeclareNamespaceElements;
public final UnusedStatementDisposition unusedStatementsDisposition;
public final String[] partnerFileSuffixes;
public IncludePreferences(ICProject project) {
includeStyles = new HashMap<IncludeKind, IncludeGroupStyle>();
loadStyle(IncludeKind.RELATED, PreferenceConstants.INCLUDE_STYLE_RELATED, project);
loadStyle(IncludeKind.PARTNER, PreferenceConstants.INCLUDE_STYLE_PARTNER, project);
loadStyle(IncludeKind.IN_SAME_FOLDER, PreferenceConstants.INCLUDE_STYLE_SAME_FOLDER, project);
loadStyle(IncludeKind.IN_SUBFOLDER, PreferenceConstants.INCLUDE_STYLE_SUBFOLDER, project);
loadStyle(IncludeKind.SYSTEM, PreferenceConstants.INCLUDE_STYLE_SYSTEM, project);
loadStyle(IncludeKind.SYSTEM_WITH_EXTENSION, PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITH_EXTENSION, project);
loadStyle(IncludeKind.SYSTEM_WITHOUT_EXTENSION, PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION, project);
loadStyle(IncludeKind.OTHER, PreferenceConstants.INCLUDE_STYLE_OTHER, project);
loadStyle(IncludeKind.IN_SAME_PROJECT, PreferenceConstants.INCLUDE_STYLE_SAME_PROJECT, project);
loadStyle(IncludeKind.IN_OTHER_PROJECT, PreferenceConstants.INCLUDE_STYLE_OTHER_PROJECT, project);
loadStyle(IncludeKind.EXTERNAL, PreferenceConstants.INCLUDE_STYLE_EXTERNAL, project);
// Unclassified includes are always kept together.
includeStyles.get(IncludeKind.OTHER).setKeepTogether(true);
// Normalize order property of the styles to make sure that the numbers are sequential.
List<IncludeGroupStyle> styles = new ArrayList<IncludeGroupStyle>(includeStyles.values());
Collections.sort(styles);
for (int i = 0; i < styles.size(); i++) {
styles.get(i).setOrder(i);
}
// TODO(sprigogin): Load styles for headers matching patterns.
forwardDeclareCompositeTypes = PreferenceConstants.getPreference(
PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES, project, true);
forwardDeclareEnums = PreferenceConstants.getPreference(
PreferenceConstants.FORWARD_DECLARE_ENUMS, project, false);
forwardDeclareFunctions = PreferenceConstants.getPreference(
PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, project, false);
forwardDeclareTemplates = PreferenceConstants.getPreference(
PreferenceConstants.FORWARD_DECLARE_TEMPLATES, project, false);
forwardDeclareNamespaceElements = PreferenceConstants.getPreference(
PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS, project, true);
String value = PreferenceConstants.getPreference(
PreferenceConstants.INCLUDES_PARTNER_FILE_SUFFIXES, project, DEFAULT_PARTNER_FILE_SUFFIXES);
partnerFileSuffixes = value.split(","); //$NON-NLS-1$
heuristicHeaderSubstitution = PreferenceConstants.getPreference(
PreferenceConstants.INCLUDES_HEURISTIC_HEADER_SUBSTITUTION, project, true);
allowReordering = PreferenceConstants.getPreference(
PreferenceConstants.INCLUDES_ALLOW_REORDERING, project, true);
// TODO(sprigogin): Create a preference for this.
allowPartnerIndirectInclusion = false;
// Unused include handling preferences
value = PreferenceConstants.getPreference(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION, project, null);
UnusedStatementDisposition disposition = null;
if (value != null)
disposition = UnusedStatementDisposition.valueOf(value);
if (disposition == null)
disposition = UnusedStatementDisposition.COMMENT_OUT;
unusedStatementsDisposition = disposition;
}
private void loadStyle(IncludeKind includeKind, String preferenceKey, ICProject project) {
String value = PreferenceConstants.getPreference(preferenceKey, project, null);
IncludeGroupStyle style = null;
if (value != null)
style = IncludeGroupStyle.fromString(value, includeKind);
if (style == null)
style = new IncludeGroupStyle(includeKind);
includeStyles.put(includeKind, style);
}
/**
* Initializes the given preference store with the default values.
*
* @param store the preference store to be initialized
*/
public static void initializeDefaultValues(IPreferenceStore store) {
IncludeGroupStyle style = new IncludeGroupStyle(IncludeKind.RELATED);
store.setDefault(PreferenceConstants.INCLUDE_STYLE_RELATED, style.toString());
style = new IncludeGroupStyle(IncludeKind.PARTNER);
style.setKeepTogether(true);
style.setBlankLineBefore(true);
style.setOrder(0);
store.setDefault(PreferenceConstants.INCLUDE_STYLE_PARTNER, style.toString());
style = new IncludeGroupStyle(IncludeKind.IN_SAME_FOLDER);
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SAME_FOLDER, style.toString());
style = new IncludeGroupStyle(IncludeKind.IN_SUBFOLDER);
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SUBFOLDER, style.toString());
style = new IncludeGroupStyle(IncludeKind.SYSTEM);
style.setKeepTogether(true);
style.setBlankLineBefore(true);
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SYSTEM, style.toString());
style = new IncludeGroupStyle(IncludeKind.SYSTEM_WITH_EXTENSION);
style.setKeepTogether(true);
style.setAngleBrackets(true);
style.setOrder(1);
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITH_EXTENSION, style.toString());
style = new IncludeGroupStyle(IncludeKind.SYSTEM_WITHOUT_EXTENSION);
style.setKeepTogether(true);
style.setAngleBrackets(true);
style.setOrder(2);
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION, style.toString());
style = new IncludeGroupStyle(IncludeKind.OTHER);
style.setKeepTogether(true);
style.setBlankLineBefore(true);
style.setOrder(3);
store.setDefault(PreferenceConstants.INCLUDE_STYLE_OTHER, style.toString());
style = new IncludeGroupStyle(IncludeKind.IN_SAME_PROJECT);
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SAME_PROJECT, style.toString());
style = new IncludeGroupStyle(IncludeKind.IN_OTHER_PROJECT);
store.setDefault(PreferenceConstants.INCLUDE_STYLE_OTHER_PROJECT, style.toString());
style = new IncludeGroupStyle(IncludeKind.EXTERNAL);
store.setDefault(PreferenceConstants.INCLUDE_STYLE_EXTERNAL, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_MATCHING_PATTERN, ""); //$NON-NLS-1$
store.setDefault(PreferenceConstants.INCLUDES_PARTNER_FILE_SUFFIXES, DEFAULT_PARTNER_FILE_SUFFIXES);
store.setDefault(PreferenceConstants.INCLUDES_HEURISTIC_HEADER_SUBSTITUTION, true);
store.setDefault(PreferenceConstants.INCLUDES_ALLOW_REORDERING, true);
store.setDefault(PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES, true);
store.setDefault(PreferenceConstants.FORWARD_DECLARE_ENUMS, false);
store.setDefault(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, false);
store.setDefault(PreferenceConstants.FORWARD_DECLARE_TEMPLATES, false);
store.setDefault(PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS, true);
store.setDefault(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION, UnusedStatementDisposition.COMMENT_OUT.toString());
}
}

View file

@ -0,0 +1,68 @@
/*******************************************************************************
* Copyright (c) 2012, 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IndexLocationFactory;
public class IncludeUtil {
/** Not instantiatable. All methods are static. */
private IncludeUtil() {}
/**
* Checks if a file is a source file (.c, .cpp, .cc, etc). Header files are not considered
* source files.
* @return Returns {@code true} if the the file is a source file.
*/
public static boolean isSource(IIndexFile file, IProject project) throws CoreException {
return isSource(getPath(file), project);
}
/**
* Checks if a file is a source file (.c, .cpp, .cc, etc). Header files are not considered
* source files.
* @return Returns {@code true} if the the file is a source file.
*/
public static boolean isSource(String filename, IProject project) {
IContentType ct= CCorePlugin.getContentType(project, filename);
if (ct != null) {
String id = ct.getId();
if (CCorePlugin.CONTENT_TYPE_CSOURCE.equals(id) || CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(id)) {
return true;
}
}
return false;
}
/**
* Returns the path of the given index file.
* @param file The index file.
* @return The path.
*/
public static String getPath(IIndexFile file) throws CoreException {
return getPath(file.getLocation());
}
/**
* Returns the path of the given index file.
* @param fileLocation The index file location.
* @return The path.
*/
public static String getPath(IIndexFileLocation fileLocation) {
return IndexLocationFactory.getAbsolutePath(fileLocation).toOSString();
}
}

View file

@ -0,0 +1,183 @@
/*******************************************************************************
* Copyright (c) 2012, 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor;
import org.eclipse.cdt.internal.core.parser.scanner.IncludeSearchPath;
import org.eclipse.cdt.internal.core.parser.scanner.IncludeSearchPathElement;
import org.eclipse.cdt.internal.core.parser.scanner.ScannerUtility;
/**
* Context for managing include statements.
*/
public class InclusionContext {
private static final IPath UNRESOLVED_INCLUDE = Path.EMPTY;
private final ITranslationUnit fTu;
private final IProject fProject;
private final IPath fCurrentDirectory;
private final IncludePreferences fPreferences;
private final IncludeSearchPath fIncludeSearchPath;
private final Map<IncludeInfo, IPath> fIncludeResolutionCache;
private final Map<IPath, IncludeInfo> fInverseIncludeResolutionCache;
private final IIndex fIndex;
private final Set<IPath> fHeadersToInclude;
private final Set<IPath> fHeadersAlreadyIncluded;
public InclusionContext(ITranslationUnit tu, IIndex index) {
fTu = tu;
fIndex = index;
ICProject cProject = fTu.getCProject();
fPreferences = new IncludePreferences(cProject);
fProject = cProject.getProject();
fCurrentDirectory = fTu.getResource().getParent().getLocation();
IScannerInfo scannerInfo = fTu.getScannerInfo(true);
fIncludeSearchPath = CPreprocessor.configureIncludeSearchPath(fCurrentDirectory.toFile(), scannerInfo);
fIncludeResolutionCache = new HashMap<IncludeInfo, IPath>();
fInverseIncludeResolutionCache = new HashMap<IPath, IncludeInfo>();
fHeadersToInclude = new HashSet<IPath>();
fHeadersAlreadyIncluded = new HashSet<IPath>();
}
public ITranslationUnit getTranslationUnit() {
return fTu;
}
public IIndex getIndex() {
return fIndex;
}
public IProject getProject() {
return fProject;
}
public IncludePreferences getPreferences() {
return fPreferences;
}
public boolean isCXXLanguage() {
return fTu.isCXXLanguage();
}
public IPath getCurrentDirectory() {
return fCurrentDirectory;
}
public IPath resolveInclude(IncludeInfo include) {
IPath path = fIncludeResolutionCache.get(include);
if (path == null) {
String directory = fCurrentDirectory.toOSString();
String filePath = CPreprocessor.getAbsoluteInclusionPath(include.getName(), directory);
if (filePath != null) {
path = new Path(filePath);
} else if (!include.isSystem() && !fIncludeSearchPath.isInhibitUseOfCurrentFileDirectory()) {
// Check to see if we find a match in the current directory.
filePath = ScannerUtility.createReconciledPath(directory, include.getName());
if (fileExists(filePath)) {
path = new Path(filePath);
}
}
if (path == null) {
for (IncludeSearchPathElement pathElement : fIncludeSearchPath.getElements()) {
if (include.isSystem() && pathElement.isForQuoteIncludesOnly())
continue;
filePath = pathElement.getLocation(include.getName());
if (fileExists(filePath)) {
path = new Path(filePath);
break;
}
}
}
if (path == null)
path = UNRESOLVED_INCLUDE;
fIncludeResolutionCache.put(include, path);
fInverseIncludeResolutionCache.put(path, include);
}
return path == UNRESOLVED_INCLUDE ? null : path;
}
/**
* Returns the include directive that resolves to the given header file, or {@code null} if
* the file is not on the include search path. Current directory is not considered to be a part
* of the include path by this method.
*/
public IncludeInfo getIncludeForHeaderFile(IPath fullPath) {
IncludeInfo include = fInverseIncludeResolutionCache.get(fullPath);
if (include != null)
return include;
String headerLocation = fullPath.toOSString();
String shortestInclude = null;
boolean isSystem = false;
for (IncludeSearchPathElement pathElement : fIncludeSearchPath.getElements()) {
String includeDirective = pathElement.getIncludeDirective(headerLocation);
if (includeDirective != null &&
(shortestInclude == null || shortestInclude.length() > includeDirective.length())) {
shortestInclude = includeDirective;
isSystem = !pathElement.isForQuoteIncludesOnly();
}
}
if (shortestInclude == null)
return null;
include = new IncludeInfo(shortestInclude, isSystem);
// Don't put an include to fullPath to fIncludeResolutionCache since it may be wrong
// if the header was included by #include_next.
fInverseIncludeResolutionCache.put(fullPath, include);
return include;
}
private static boolean fileExists(String absolutePath) {
return new File(absolutePath).exists();
}
public Set<IPath> getHeadersToInclude() {
return fHeadersToInclude;
}
public final void addHeaderToInclude(IPath header) {
fHeadersToInclude.add(header);
}
public final boolean isToBeIncluded(IPath header) {
return fHeadersToInclude.contains(header);
}
public Set<IPath> getHeadersAlreadyIncluded() {
return fHeadersAlreadyIncluded;
}
public final void addHeaderAlreadyIncluded(IPath header) {
fHeadersAlreadyIncluded.add(header);
}
public final boolean isAlreadyIncluded(IPath header) {
return fHeadersAlreadyIncluded.contains(header);
}
public final boolean isIncluded(IPath header) {
return fHeadersAlreadyIncluded.contains(header) || fHeadersToInclude.contains(header);
}
}

View file

@ -0,0 +1,78 @@
/*******************************************************************************
* Copyright (c) 2012, 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IPath;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.index.IIndexFile;
class InclusionRequest {
private final IBinding fBinding;
private final Map<IIndexFile, IPath> fDeclaringFiles;
private final boolean fReachable;
private List<IPath> fCandidatePaths;
private IPath fResolvedPath;
/**
* @param binding the binding that requires inclusion
* @param declaringHeaders headers that can be included to declare the binding and paths
* that can be used to include them
* @param reachable indicates whether the headers were previously included or not
*/
public InclusionRequest(IBinding binding, Map<IIndexFile, IPath> declaringHeaders,
boolean reachable) {
fBinding = binding;
fDeclaringFiles = Collections.unmodifiableMap(declaringHeaders);
fReachable = reachable;
fCandidatePaths = new ArrayList<IPath>(new HashSet<IPath>(fDeclaringFiles.values()));
}
public IBinding getBinding() {
return fBinding;
}
public Map<IIndexFile, IPath> getDeclaringFiles() {
return fDeclaringFiles;
}
public List<IPath> getCandidatePaths() {
return fCandidatePaths;
}
public void setCandidatePaths(List<IPath> paths) {
fCandidatePaths = paths;
}
public boolean isReachable() {
return fReachable;
}
public void resolve(IPath path) {
if (fResolvedPath != null)
throw new IllegalStateException();
fResolvedPath = path;
}
public IPath getResolvedPath() {
return fResolvedPath;
}
public boolean isResolved() {
return fResolvedPath != null;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2003, 2011 IBM Corporation and others.
* Copyright (c) 2003, 2013 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
@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.ui;
@ -28,6 +29,7 @@ import org.eclipse.cdt.internal.ui.preferences.CEditorPreferencePage;
import org.eclipse.cdt.internal.ui.preferences.CPluginPreferencePage;
import org.eclipse.cdt.internal.ui.preferences.CodeAssistPreferencePage;
import org.eclipse.cdt.internal.ui.preferences.WorkInProgressPreferencePage;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences;
/**
* This class implements the setting of the CUI initial preference store settings.
@ -49,6 +51,7 @@ public class CUIPreferenceInitializer extends AbstractPreferenceInitializer {
CView.initDefaults(store);
CEditorPreferencePage.initDefaults(store);
CodeAssistPreferencePage.initDefaults(store);
IncludePreferences.initializeDefaultValues(store);
SemanticHighlightings.initDefaults(store);
WorkInProgressPreferencePage.initDefaults(store);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2011 IBM Corporation and others.
* Copyright (c) 2005, 2012 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
@ -1953,6 +1953,197 @@ public class PreferenceConstants {
*/
public static final String FUNCTION_PASS_OUTPUT_PARAMETERS_BY_POINTER = "function_pass_output_parameters_by_pointer"; //$NON-NLS-1$
/**
* Whether composite types should be forward declared if possible.
*
* Examples:
* class X;
* struct Y;
* union Z;
*
* @since 5.6
*/
public static final String FORWARD_DECLARE_COMPOSITE_TYPES = "forwardDeclare.compositeTypes"; //$NON-NLS-1$
/**
* Whether C++11-style enums should be forward declared if possible.
*
* Example:
* enum class X;
*
* @since 5.6
*/
public static final String FORWARD_DECLARE_ENUMS = "forwardDeclare.enums"; //$NON-NLS-1$
/**
* Whether C-style functions should be forward declared if possible.
*
* Example:
* void foo();
*
* @since 5.6
*/
public static final String FORWARD_DECLARE_FUNCTIONS = "forwardDeclare.functions"; //$NON-NLS-1$
/**
* Whether C++ templates should be forward declared if possible.
*
* Examples:
* template<typename T> class foo;
* template<typename T> void bar(T p);
*
* @since 5.6
*/
public static final String FORWARD_DECLARE_TEMPLATES = "forwardDeclare.templates"; //$NON-NLS-1$
/**
* Whether elements nested within namespaces should be forward declared if possible.
*
* Examples:
* namespace N { class X; }
*
* @since 5.6
*/
public static final String FORWARD_DECLARE_NAMESPACE_ELEMENTS = "forwardDeclare.namespaceElements"; //$NON-NLS-1$
/**
* Defines a list of file name suffixes. A header file and the including file are considered
* partners if their file names without extensions are either identical or differ by one of
* these suffixes.
*
* @since 5.6
*/
public static final String INCLUDES_PARTNER_FILE_SUFFIXES = "includes.partnerFileSuffixes"; //$NON-NLS-1$
/**
* Whether a heuristic approach should be used to decide which C++ header files to include.
* The heuristic prefers headers which have no file extension and / or are named like the symbol
* which should be defined. This often works out nicely since it's a commonly used naming
* convention for C++ library headers.
*
* @since 5.6
*/
public static final String INCLUDES_HEURISTIC_HEADER_SUBSTITUTION = "organizeIncludes.heuristicHeader_substitution"; //$NON-NLS-1$
/**
* Whether it's allowed to reorder existing include directives. If this preference is set to
* false, the original order is kept as far as possible. This may be necessary to avoid breaking
* code which makes assumptions about the order of the include directives. If this is set to
* true, a different sort order can be applied. Groups of includes are ordered according to
* the values returned by
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle#getOrder()} method.
* Includes within each group are ordered alphabetically.
*
* @since 5.6
*/
public static final String INCLUDES_ALLOW_REORDERING = "organizeIncludes.allowReordering"; //$NON-NLS-1$
/**
* Determines what should be done with any unused include directives and forward declarations.
* This preference may have one of the three values defined by
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences.UnusedStatementDisposition}
* enumeration ("REMOVE", "COMMENT_OUT", "KEEP").
*
* @since 5.6
*/
public static final String INCLUDES_UNUSED_STATEMENTS_DISPOSITION = "organizeIncludes.unusedStatements"; //$NON-NLS-1$
/**
* Include style for headers closely related to the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_RELATED = "includeStyle.related"; //$NON-NLS-1$
/**
* Include style for the header with the same name as the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_PARTNER = "includeStyle.partner"; //$NON-NLS-1$
/**
* Include style for headers in the same folder as the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SAME_FOLDER = "includeStyle.sameFolder"; //$NON-NLS-1$
/**
* Include style for headers in subfolders of the folder containing the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SUBFOLDER = "includeStyle.subfolder"; //$NON-NLS-1$
/**
* Include style for system headers.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SYSTEM = "includeStyle.system"; //$NON-NLS-1$
/**
* Include style for C-style system headers with a file name extension.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SYSTEM_WITH_EXTENSION = "includeStyle.systemWithExtension"; //$NON-NLS-1$
/**
* Include style for C++-style system headers without a file name extension.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION = "includeStyle.systemWithoutExtension"; //$NON-NLS-1$
/**
* Include style for headers not closely related to the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_OTHER = "includeStyle.other"; //$NON-NLS-1$
/**
* Include style for headers in the same project as the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SAME_PROJECT = "includeStyle.inSameProject"; //$NON-NLS-1$
/**
* Include style for headers in a different project than the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_OTHER_PROJECT = "includeStyle.inOtherProject"; //$NON-NLS-1$
/**
* Include style for headers outside Eclipse workspace.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_EXTERNAL = "includeStyle.external"; //$NON-NLS-1$
/**
* Include styles for headers matching user-defined patterns.
* The value of the preference is an XML representation of one or more
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}s.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_MATCHING_PATTERN = "includeStyle.matchingPattern"; //$NON-NLS-1$
/**
* Returns the CDT-UI preference store.
@ -2232,7 +2423,7 @@ public class PreferenceConstants {
* the workspace setting should be taken. Note that passing {@code null} should
* be avoided.
* @param defaultValue The default value if not specified in the preferences.
* @return Returns the current value for the string.
* @return Returns the current value of the preference.
* @since 5.1
*/
public static int getPreference(String key, ICProject project, int defaultValue) {
@ -2245,7 +2436,7 @@ public class PreferenceConstants {
* @param project The current context or {@code null} if no context is available and
* the workspace setting should be taken. Note that passing {@code null} should be avoided.
* @param defaultValue The default value if not specified in the preferences.
* @return Returns the current value for the string.
* @return Returns the current value of the preference.
* @since 5.1
*/
public static boolean getPreference(String key, ICProject project, boolean defaultValue) {

View file

@ -139,6 +139,13 @@ public class CdtActionConstants {
*/
public static final String ADD_INCLUDE= "org.eclipse.cdt.ui.actions.AddInclude"; //$NON-NLS-1$
/**
* Source menu: name of standard Organize Includes global action
* (value <code>"org.eclipse.cdt.ui.actions.OrganizeIncludes"</code>).
* @since 5.6
*/
public static final String ORGANIZE_INCLUDES= "org.eclipse.cdt.ui.actions.OrganizeIncludes"; //$NON-NLS-1$
/**
* Source menu: name of standard Sort Lines global action
* (value <code>"org.eclipse.cdt.ui.actions.SortLines"</code>).

View file

@ -52,6 +52,7 @@ import org.eclipse.cdt.internal.ui.actions.CDTQuickMenuCreator;
import org.eclipse.cdt.internal.ui.editor.AddIncludeOnSelectionAction;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.editor.ICEditorActionDefinitionIds;
import org.eclipse.cdt.internal.ui.editor.OrganizeIncludesAction;
import org.eclipse.cdt.internal.ui.editor.SortLinesAction;
/**
@ -128,7 +129,7 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange
// private ExternalizeStringsAction fExternalizeStrings;
// private CleanUpAction fCleanUp;
//
// private OrganizeIncludesAction fOrganizeIncludes;
private OrganizeIncludesAction fOrganizeIncludes;
// private SortMembersAction fSortMembers;
private SortLinesAction fSortLines;
private FormatAllAction fFormatAll;
@ -158,10 +159,10 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange
fAddInclude.setActionDefinitionId(ICEditorActionDefinitionIds.ADD_INCLUDE);
editor.setAction("AddIncludeOnSelection", fAddInclude); //$NON-NLS-1$
// fOrganizeIncludes= new OrganizeIncludesAction(editor);
// fOrganizeIncludes.setActionDefinitionId(ICEditorActionDefinitionIds.ORGANIZE_INCLUDES);
// editor.setAction("OrganizeIncludes", fOrganizeIncludes); //$NON-NLS-1$
//
fOrganizeIncludes= new OrganizeIncludesAction(editor);
fOrganizeIncludes.setActionDefinitionId(ICEditorActionDefinitionIds.ORGANIZE_INCLUDES);
editor.setAction("OrganizeIncludes", fOrganizeIncludes); //$NON-NLS-1$
// fSortMembers= new SortMembersAction(editor);
// fSortMembers.setActionDefinitionId(ICEditorActionDefinitionIds.SORT_MEMBERS);
// editor.setAction("SortMembers", fSortMembers); //$NON-NLS-1$
@ -431,7 +432,7 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange
added+= addEditorAction(source, "Format"); //$NON-NLS-1$
source.add(new Separator(GROUP_ORGANIZE));
added+= addAction(source, fAddInclude);
// added+= addAction(source, fOrganizeIncludes);
added+= addAction(source, fOrganizeIncludes);
// added+= addAction(source, fSortMembers);
added+= addAction(source, fSortLines);
// added+= addAction(source, fCleanUp);
@ -457,7 +458,7 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange
added+= addAction(source, fFormatAll);
source.add(new Separator(GROUP_ORGANIZE));
added+= addAction(source, fAddInclude);
// added+= addAction(source, fOrganizeIncludes);
added+= addAction(source, fOrganizeIncludes);
// added+= addAction(source, fSortMembers);
// added+= addAction(source, fCleanUp);
source.add(new Separator(GROUP_GENERATE));
@ -506,7 +507,7 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange
// actionBar.setGlobalActionHandler(CdtActionConstants.ADD_CPP_DOC_COMMENT, fAddCppDocStub);
// actionBar.setGlobalActionHandler(CdtActionConstants.EXTERNALIZE_STRINGS, fExternalizeStrings);
// actionBar.setGlobalActionHandler(CdtActionConstants.CLEAN_UP, fCleanUp);
// actionBar.setGlobalActionHandler(CdtActionConstants.ORGANIZE_INCLUDES, fOrganizeIncludes);
// TODO: actionBar.setGlobalActionHandler(CdtActionConstants.ORGANIZE_INCLUDES, fOrganizeIncludes);
// actionBar.setGlobalActionHandler(CdtActionConstants.SORT_MEMBERS, fSortMembers);
if (!isEditorOwner()) {
// editor provides its own implementation of these actions.

View file

@ -10,7 +10,7 @@ Export-Package:
org.eclipse.cdt.debug.internal.ui;x-internal:x-friends:="org.eclipse.cdt.dsf.ui";x-friends:="org.eclipse.cdt.dsf.ui",
org.eclipse.cdt.debug.internal.ui.actions;x-friends:="org.eclipse.cdt.dsf.ui,org.eclipse.cdt.debug.ui.memory.memorybrowser",
org.eclipse.cdt.debug.internal.ui.actions.breakpoints;x-internal:=true,
org.eclipse.cdt.debug.internal.ui.breakpoints;x-friends:="org.eclipse.cdt.dsf.ui",
org.eclipse.cdt.debug.internal.ui.breakpoints;x-friends:="org.eclipse.cdt.dsf.ui,org.eclipse.cdt.dsf.gdb.ui",
org.eclipse.cdt.debug.internal.ui.commands;x-internal:=true,
org.eclipse.cdt.debug.internal.ui.dialogfields;x-friends:="org.eclipse.cdt.dsf.gdb.ui",
org.eclipse.cdt.debug.internal.ui.dialogs;x-internal:=true,

View file

@ -41,3 +41,7 @@ CBreakpointPropertyPage.enabled_label=Enabled
CBreakpointPropertyPage.eventType_label=Event Type
ThreadFilterEditor.0=&Restrict to Selected Targets and Threads:
TracepointPropertyPage.tracepointType_function_label=C/C++ Function Tracepoint
TracepointPropertyPage.tracepointType_address_label=C/C++ Address Tracepoint
TracepointPropertyPage.tracepointType_line_label=C/C++ Line Tracepoint

View file

@ -177,11 +177,23 @@ class CBreakpointContextWorkbenchAdapter implements IWorkbenchAdapter {
private String getBreakpointMainLabel(ICBreakpoint breakpoint) {
if (breakpoint instanceof ICFunctionBreakpoint) {
return BreakpointsMessages.getString("CBreakpointPropertyPage.breakpointType_function_label"); //$NON-NLS-1$
if (breakpoint instanceof ICTracepoint) {
return BreakpointsMessages.getString("TracepointPropertyPage.tracepointType_function_label"); //$NON-NLS-1$
} else {
return BreakpointsMessages.getString("CBreakpointPropertyPage.breakpointType_function_label"); //$NON-NLS-1$
}
} else if (breakpoint instanceof ICAddressBreakpoint) {
return BreakpointsMessages.getString("CBreakpointPropertyPage.breakpointType_address_label"); //$NON-NLS-1$
if (breakpoint instanceof ICTracepoint) {
return BreakpointsMessages.getString("TracepointPropertyPage.tracepointType_address_label"); //$NON-NLS-1$
} else {
return BreakpointsMessages.getString("CBreakpointPropertyPage.breakpointType_address_label"); //$NON-NLS-1$
}
} else if (breakpoint instanceof ICLineBreakpoint) {
return BreakpointsMessages.getString("CBreakpointPropertyPage.breakpointType_line_label"); //$NON-NLS-1$
if (breakpoint instanceof ICTracepoint) {
return BreakpointsMessages.getString("TracepointPropertyPage.tracepointType_line_label"); //$NON-NLS-1$
} else {
return BreakpointsMessages.getString("CBreakpointPropertyPage.breakpointType_line_label"); //$NON-NLS-1$
}
} else if (breakpoint instanceof ICEventBreakpoint) {
return BreakpointsMessages.getString("CBreakpointPropertyPage.breakpointType_event_label"); //$NON-NLS-1$
} else if (breakpoint instanceof ICWatchpoint) {

View file

@ -8,6 +8,7 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
* QNX Software Systems - Refactored to use platform implementation
* Marc Khouzam (Ericsson) - Added support for Tracepoints (bug 376116)
*******************************************************************************/
package org.eclipse.cdt.debug.internal.ui.breakpoints;
@ -23,6 +24,7 @@ import java.util.Set;
import org.eclipse.cdt.debug.core.CDIDebugModel;
import org.eclipse.cdt.debug.core.model.ICBreakpoint;
import org.eclipse.cdt.debug.core.model.ICLineBreakpoint2;
import org.eclipse.cdt.debug.core.model.ICTracepoint;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
@ -36,7 +38,8 @@ import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
/**
* A preference store that presents the state of the properties of a C/C++ breakpoint.
* A preference store that presents the state of the properties of a C/C++ breakpoint
* or Tracepoint.
*/
public class CBreakpointPreferenceStore implements IPersistentPreferenceStore {
@ -131,6 +134,9 @@ public class CBreakpointPreferenceStore implements IPersistentPreferenceStore {
else if ( property.equals( ICBreakpoint.IGNORE_COUNT ) ) {
breakpoint.setIgnoreCount( getInt( ICBreakpoint.IGNORE_COUNT ) );
}
else if ( breakpoint instanceof ICTracepoint && property.equals( ICTracepoint.PASS_COUNT ) ) {
((ICTracepoint)breakpoint).setPassCount( getInt( ICTracepoint.PASS_COUNT ) );
}
else if ( property.equals( ICBreakpoint.CONDITION ) ) {
breakpoint.setCondition( getString( ICBreakpoint.CONDITION ) );
}

View file

@ -134,7 +134,7 @@
</p>
<a name="Build"></a><h2> <span class="headline"> Build </span></h2>
<a name="Scanner_Discovery"></a><h3> <span class="headline"> Scanner Discovery </span></h3>
<p>Scanner Discovery has been reworked in this release. The main purpose of Scanner Discovery was always to supply Include Paths and Macros for indexer and build. Now these are supplied by Language Settings Providers. See more at <a href="../../scannerdiscovery61/index.html" class="external text" title="http://wiki.eclipse.org/CDT/ScannerDiscovery61" rel="nofollow">Scanner Discovery Wiki</a>
<p>Scanner Discovery has been reworked in this release. The main purpose of Scanner Discovery was always to supply Include Paths and Macros for indexer and build. Now these are supplied by Language Settings Providers. See more at <a href="http://wiki.eclipse.org/CDT/ScannerDiscovery61" class="external text">Scanner Discovery</a> on the wiki.
</p><p><img alt="Image:sd90Entries.png" src="../images/cdt81/sd90entries.png" width="1111" height="736" border="0" />
</p><p><img alt="Image:sd90Providers.png" src="../images/cdt81/sd90providers.png" width="1177" height="736" border="0" />
</p><p><br />
@ -372,7 +372,7 @@
</li><li>test runs history;
</li><li>the list of provided tests runners may be easily extended writing a new Tests Runner Plugin.
</li></ul>
<p>The HOWTO, known problems and limitation can be found in the <a href="../faq/index.html#C.2FC.2B.2B_Unit_Testing_Support" class="external text" title="http://wiki.eclipse.org/CDT/User/FAQ#C.2FC.2B.2B_Unit_Testing_Support" rel="nofollow">corresponding section of CDT FAQ</a>.
<p>The HOWTO, known problems and limitation can be found in the <a href="http://wiki.eclipse.org/CDT/User/FAQ#C.2FC.2B.2B_Unit_Testing_Support" class="external text">CDT FAQ</a> on the wiki.
</p><p>This feature was completed April 18th, 2012 as part of <a href="http://bugs.eclipse.org/210366" class="external text" title="http://bugs.eclipse.org/210366" rel="nofollow">Bug 210366</a>.
</p>
<a name="Bugs_Fixed"></a><h2> <span class="headline"> Bugs Fixed in this Release </span></h2>

30
doc/org.eclipse.cdt.doc.user/contexts_CDT.xml Normal file → Executable file
View file

@ -147,41 +147,11 @@
<topic href="reference/cdt_u_discovery_preferences.htm"
label="Discovery Options"/>
</context>
<context id ="man_prop_info">
<description>Click below to see help.</description>
<topic href="reference/cdt_u_mprop_info.htm"
label="Info"/>
</context>
<context id ="man_prop_builder">
<description>Click below to see help.</description>
<topic href="reference/cdt_u_mprop_builders.htm"
label="Builders"/>
</context>
<context id ="man_prop_build">
<description>Click below to see help.</description>
<topic href="reference/cdt_u_mprop_build.htm"
label="Build"/>
</context>
<context id ="man_prop_file_types">
<description>Click below to see help.</description>
<topic href="reference/cdt_u_mprop_file_types.htm"
label="File Types"/>
</context>
<context id ="man_prop_indexer">
<description>Click below to see help.</description>
<topic href="reference/cdt_u_prop_general_idx.htm"
label="Indexer"/>
</context>
<context id ="man_prop_error">
<description>Click below to see help.</description>
<topic href="reference/cdt_u_mprop_merror.htm"
label="Error Parser"/>
</context>
<context id ="man_prop_references">
<description>Click below to see help.</description>
<topic href="reference/cdt_u_mprop_ref.htm"
label="Project References"/>
</context>
<context id ="std_prop_info">
<description>Click below to see help.</description>
<topic href="reference/cdt_u_sprop_info.htm"

View file

@ -1,71 +1,85 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Preparing the Workbench</title>
<link rel="stylesheet" type="text/css" href="../help.css">
<script language="JavaScript">
function newWin(url) {
window.open(url, 'install_cdt', 'width=750, height=700, menubar=no, toolbar=no, status=no, resizable=yes, location=no, scrollbars=yes');
}
</script>
<script type="text/javascript"
src="PLUGINS_ROOT/org.eclipse.help/livehelp.js"></script>
</head>
<body>
<div role="main"><h1>Preparing the Workbench</h1>
<div role="main">
<h1>Preparing the Workbench</h1>
<p>This tutorial will get you started using the C/C++ Development Toolkit (CDT) in the Workbench.</p>
<p>First, you will verify that the workbench is properly configured for C/C++ development. It is assumed that:</p>
<ul>
<li>Your Workbench has its default settings.
To reset the current perspective to its original layout, from the menu bar select
<strong>Window &gt; Reset Perspective</strong>.</li>
<li>You are familiar with the basic Workbench features, such as
<a href="../concepts/cdt_c_views.htm">views</a> and
<a href="../concepts/cdt_c_perspectives.htm">perspectives</a>.
</li>
</ul>
<p>This tutorial will get you started using the C/C++ Development
Toolkit (CDT) in the Workbench.</p>
<p>First, you will verify that the workbench is properly
configured for C/C++ development. It is assumed that:</p>
<ul>
<li>Your Workbench has its default settings. To reset the
current perspective to its original layout, from the menu bar select
<strong>Window &gt; Reset Perspective</strong>.
</li>
<li>You are familiar with the basic Workbench features, such as
<a href="../concepts/cdt_c_views.htm">views</a> and <a
href="../concepts/cdt_c_perspectives.htm">perspectives</a>.
</li>
</ul>
<h2>Setting the global editor operations and appearance</h2>
<h2>Setting the global editor operations and appearance</h2>
<ul>
<li>Click <strong>Window &gt; Preferences &gt; General &gt; Editors</strong> to access global editor related preference panels, including.
<ul>
<li>File Associations</li>
<li>Structured Text Editor</li>
<li>Text Editors</li>
</ul>
</li>
</ul>
<h2>Setting the C/C++ editor operations and appearance</h2>
<ul>
<li>Click <strong>Window &gt; Preferences &gt; C/C++ &gt; Editor </strong>to access C/C++ editor preference panels, inlcuding:
<ul>
<li><a href="../reference/cdt_u_c_editor_gen.htm">Editor</a> - control the appearance of text highlighting</li>
<li><a href="../reference/cdt_u_c_editor_con_assist.htm">Content Assist </a>- customize the Content Assist feature</li>
<li><a href="../reference/cdt_u_c_editor_folding.htm">Folding</a> - customize folding behavior in the C/C++ editor</li>
<li><a href="../reference/cdt_u_c_editor_hov.htm">Hovering</a> - customize hover behavior in the C/C++ editor </li>
<li><a href="../reference/cdt_u_c_editor_mark_occurrences.htm">Mark Occurances</a> - set annotations for the C/C++ Editor view</li>
<li><a href="../reference/cdt_u_c_editor_save_actions.htm">Save Actions</a> - configure actions performed while saving a file</li>
<li><a href="../reference/cdt_u_c_editor_scalability.htm">Scalability</a> - configure behavior for handling large source files</li>
<li><a href="../reference/cdt_u_c_editor_color.htm">Syntax Coloring</a> - specify how C/C++ source code is rendered</li>
<li><a href="../reference/cdt_u_c_code_templates_pref.htm">Templates</a> - configure the format of newly generated code stubs, comments and files</li>
<li><a href="../reference/cdt_u_c_editor_typing.htm">Typing</a> - configure formatting input as you type</li>
</ul>
</li>
</ul>
<p><img src="../images/ngref.gif" alt="Related reference">
<br><a href="../reference/cdt_o_ceditor_pref.htm">C/C++ Editor Preferences</a></p>
<p>
The main place to configure global editor-related preferences is the
<a class="command-link"
href='javascript:executeCommand("org.eclipse.ui.window.preferences(preferencePageId=org.eclipse.ui.preferencePages.Editors)")'>
<img src="PLUGINS_ROOT/org.eclipse.help/command_link.png"
alt="command link" />General &gt; Editors
</a> preference pages (also accessible through the <strong>Window
&gt; Preferences</strong> menu item)
</p>
<h2>Setting the C/C++ editor operations and appearance</h2>
<p>
C/C++-specific editor preferences are under <a class="command-link"
href='javascript:executeCommand("org.eclipse.ui.window.preferences(preferencePageId=org.eclipse.cdt.ui.preferences.CEditorPreferencePage)")'>
<img src="PLUGINS_ROOT/org.eclipse.help/command_link.png"
alt="command link" />C/C++ &gt; Editor.
</a> They include the following:
</p>
<p>
<img src="../images/rh03_04.gif" ALT="Red Hat Copyright Statement"><br>
<img src="../images/ng00_04a.gif" ALT="IBM Copyright Statement" >
</p>
</div></body>
</html>
<ul>
<li><a href="../reference/cdt_u_c_editor_gen.htm">Editor</a> -
control the appearance of text highlighting</li>
<li><a href="../reference/cdt_u_c_editor_con_assist.htm">Content
Assist </a>- customize the Content Assist feature</li>
<li><a href="../reference/cdt_u_c_editor_folding.htm">Folding</a>
- customize folding behavior</li>
<li><a href="../reference/cdt_u_c_editor_hov.htm">Hovering</a> -
customize hover behavior</li>
<li><a href="../reference/cdt_u_c_editor_mark_occurrences.htm">Mark
Occurrences</a> - set annotations</li>
<li><a href="../reference/cdt_u_c_editor_save_actions.htm">Save
Actions</a> - configure actions performed while saving a file</li>
<li><a href="../reference/cdt_u_c_editor_scalability.htm">Scalability</a>
- configure behavior for handling large source files</li>
<li><a href="../reference/cdt_u_c_editor_color.htm">Syntax
Coloring</a> - specify how C/C++ source code is rendered</li>
<li><a href="../reference/cdt_u_c_code_templates_pref.htm">Templates</a>
- configure the format of newly generated code stubs, comments and
files</li>
<li><a href="../reference/cdt_u_c_editor_typing.htm">Typing</a>
- configure formatting input as you type</li>
</ul>
<p>
<img src="../images/ngref.gif" alt="Related reference"> <br>
<a href="../reference/cdt_o_ceditor_pref.htm">C/C++ Editor
Preferences</a>
</p>
<p>
<img alt="Red Hat Copyright Statement" src="../images/rh03_04.gif"><br>
<img alt="IBM Copyright Statement" src="../images/ng00_04a.gif">
</p>
</div>
</body>
</html>

View file

@ -14,26 +14,8 @@
<p><img src="../images/cdt_menubar.png"
alt="C/C++ perspective main menu">
</p>
<img src="../images/trans.gif" width="25" height="1" alt="">
<a style="text-decoration:none" href="cdt_u_m_file.htm">File Menu actions</a><br>
<img src="../images/trans.gif" width="25" height="1" alt="">
<a style="text-decoration:none" href="cdt_u_m_edit.htm">Edit Menu actions</a><br>
<img src="../images/trans.gif" width="25" height="1" alt="">
<a style="text-decoration:none" href="cdt_u_m_source.htm">Source Menu actions</a><br>
<img src="../images/trans.gif" width="25" height="1" alt="">
<a style="text-decoration:none" href="cdt_u_m_refactor.htm">Refactor Menu actions</a><br>
<img src="../images/trans.gif" width="25" height="1" alt="">
<a style="text-decoration:none" href="cdt_u_m_navigate.htm">Navigate Menu actions</a><br>
<img src="../images/trans.gif" width="25" height="1" alt="">
<a style="text-decoration:none" href="cdt_u_m_search.htm">Search Menu actions</a><br>
<img src="../images/trans.gif" width="25" height="1" alt="">
<a style="text-decoration:none" href="cdt_u_m_project.htm">Project Menu actions</a><br>
<img src="../images/trans.gif" width="25" height="1" alt="">
<a style="text-decoration:none" href="cdt_u_m_run.htm">Run Menu actions</a><br>
<img src="../images/trans.gif" width="25" height="1" alt="">
<a style="text-decoration:none" href="cdt_u_m_window.htm">Window Menu actions</a><br>
<img src="../images/trans.gif" width="25" height="1" alt="">
<a style="text-decoration:none" href="PLUGINS_ROOT/org.eclipse.platform.doc.user/reference/ref-61.htm">Help Menu actions</a> (from Workbench User Guide)<br>
<!--INSERT_CHILD_LINKS-->
<p><img src="../images/ng00_04a.gif" ALT="IBM Copyright Statement" >
</p>
</div></body>

View file

@ -17,9 +17,6 @@ entire workspace.</p>
<img src="../images/mpref.png" width="580" height="525" alt="Managed Build preference page"></p>
<p style="margin-top: 0">The following settings may be customized:</p>
<ul>
<li>
<p style="margin-top: 0"><a href="cdt_o_mproj_pref_env.htm">Build
Environment Settings</a></li>
<li>
<p style="margin-top: 0"><a href="cdt_o_mproj_pref_macro.htm">Build Macros
Settings</a></li>

View file

@ -26,16 +26,6 @@ Each table contains three columns<strong>:</strong></p>
Macros</strong> table. A user-defined macro overrides a non user-defined macro of the same
name.&nbsp; Overridden macros are displayed in bold in
the <strong>System Macros</strong> table.</p>
<p class="MsoNormal">For more detailed information about managed make project build macros
settings, see the description in the <a href="cdt_u_mprop_macros.htm">Build Macros Property Pages</a>.</p>
<p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><img src="../images/ngref.gif" ALT="Related reference" width="143" height="21"></p>
<p style="margin-top: 0; margin-bottom:0"><a href="cdt_u_mprop_env.htm">C/C++
Project Properties, Managed, C/C++ Build, Environment</a></p>
<p style="margin-top: 0; margin-bottom:0"><a href="cdt_u_mprop_macros.htm">C/C++
Project Properties, Managed, C/C++ Build, Macros</a></p>
<p style="margin-top: 0; margin-bottom:0"><a href="cdt_o_mproj_pref_env.htm">
Managed Build Project preferences, Environment</a></p>
<p><img src="../images/intl_05.gif" ALT="Intel Copyright Statement" ></p>
</div></body>
</html>

View file

@ -5,6 +5,8 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Edit Menu actions</title>
<link rel="stylesheet" type="text/css" href="../help.css">
<script type="text/javascript"
src="PLUGINS_ROOT/org.eclipse.help/livehelp.js"></script>
</head>
<body>
<div role="main">
@ -166,8 +168,11 @@
<tr>
<td class="menu_name" headers="name">Smart Insert Mode</td>
<td headers="function">Toggles the Smart Insert mode (i.e. the
auto-completion features defined in <strong>C/C++ &gt;
Editor &gt; Typing</strong>)
auto-completion features defined in <a class="command-link"
href='javascript:executeCommand("org.eclipse.ui.window.preferences(preferencePageId=org.eclipse.cdt.ui.preferences.SmartTypingPreferencePage)")'>
<img src="PLUGINS_ROOT/org.eclipse.help/command_link.png"
alt="command link" /> C/C++ &gt; Editor &gt; Typing
</a>)
</td>
<td headers="keyboard">Ctrl+Shift+Insert</td>
</tr>

Some files were not shown because too many files have changed in this diff Show more