diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java index df6f7d2ee5c..79a7880705b 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakeBuilder.java @@ -256,24 +256,12 @@ public class MakeBuilder extends ACBuilder { getProject().setSessionProperty(qName, !monitor.isCanceled() && !isClean ? new Integer(streamMon.getWorkDone()) : null); if (errMsg != null) { - StringBuffer buf = new StringBuffer(buildCommand.toString() + " "); //$NON-NLS-1$ - for (String buildArgument : buildArguments) { - buf.append(buildArgument); - buf.append(' '); - } - - String errorDesc = MakeMessages.getFormattedString("MakeBuilder.buildError", buf.toString()); //$NON-NLS-1$ - buf = new StringBuffer(errorDesc); - buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ - buf.append("(").append(errMsg).append(")"); //$NON-NLS-1$ //$NON-NLS-2$ - cos.write(buf.toString().getBytes()); - cos.flush(); + consoleErr.write((errMsg + '\n').getBytes()); } stdout.close(); stderr.close(); - monitor.subTask(MakeMessages.getString("MakeBuilder.Creating_Markers")); //$NON-NLS-1$ consoleOut.close(); consoleErr.close(); cos.close(); diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/MakeMessages.properties b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/MakeMessages.properties index dbeb9de63d2..7509f90aa47 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/MakeMessages.properties +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/MakeMessages.properties @@ -13,7 +13,6 @@ AbstractGCCBOPConsoleParser_EnteringDirectory=Entering directory AbstractGCCBOPConsoleParser_LeavingDirectory=Leaving directory -MakeBuilder.buildError=Error launching builder ({0}) MakeBuilder.Invoking_Make_Builder=Invoking Make Builder... MakeBuilder.Invoking_Command=Invoking Command: MakeBuilder.Updating_project=Updating project... @@ -41,9 +40,7 @@ ExternalScannerInfoProvider.Reading_Specs=Reading specs ... ExternalScannerInfoProvider.Invoking_Command=Invoking Command: ExternalScannerInfoProvider.Parsing_Output=Parsing output ... ExternalScannerInfoProvider.Creating_Markers=Generating markers ... -# Error_Prefix affects generation of markers in the Problems view -ExternalScannerInfoProvider.Error_Prefix=Warning: -ExternalScannerInfoProvider.Provider_Error=Error launching external scanner info generator ({0}) +ExternalScannerInfoProvider.Provider_Error=Warning: Error launching external scanner info generator ({0}) ExternalScannerInfoProvider.Working_Directory=Working directory: {0} ExternalScannerInfoProvider.Program_Not_In_Path=Program ''{0}'' is not found in $PATH diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/DefaultRunSIProvider.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/DefaultRunSIProvider.java index 5dd879706fc..19123121aa0 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/DefaultRunSIProvider.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig2/DefaultRunSIProvider.java @@ -37,7 +37,6 @@ import org.eclipse.cdt.make.internal.core.StreamMonitor; import org.eclipse.cdt.make.internal.core.scannerconfig.ScannerConfigUtil; import org.eclipse.cdt.make.internal.core.scannerconfig.ScannerInfoConsoleParserFactory; import org.eclipse.cdt.utils.EFSExtensionManager; -import org.eclipse.cdt.utils.PathUtil; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; @@ -55,55 +54,53 @@ import org.osgi.service.prefs.BackingStoreException; * @author vhirsl */ public class DefaultRunSIProvider implements IExternalScannerInfoProvider { - private static final String EXTERNAL_SI_PROVIDER_ERROR = "ExternalScannerInfoProvider.Provider_Error"; //$NON-NLS-1$ private static final String GMAKE_ERROR_PARSER_ID = "org.eclipse.cdt.core.GmakeErrorParser"; //$NON-NLS-1$ private static final String PREF_CONSOLE_ENABLED = "org.eclipse.cdt.make.core.scanner.discovery.console.enabled"; //$NON-NLS-1$ private static final String NEWLINE = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ - private static final String PATH_ENV = "PATH"; //$NON-NLS-1$ - protected IResource resource; - protected String providerId; - protected IScannerConfigBuilderInfo2 buildInfo; - protected IScannerInfoCollector collector; - // To be initialized by a subclass - protected IPath fWorkingDirectory; - protected IPath fCompileCommand; - protected String[] fCompileArguments; + protected IResource resource; + protected String providerId; + protected IScannerConfigBuilderInfo2 buildInfo; + protected IScannerInfoCollector collector; + // To be initialized by a subclass + protected IPath fWorkingDirectory; + protected IPath fCompileCommand; + protected String[] fCompileArguments; - private SCMarkerGenerator markerGenerator = new SCMarkerGenerator(); + private SCMarkerGenerator markerGenerator = new SCMarkerGenerator(); - @Override + @Override public boolean invokeProvider(IProgressMonitor monitor, IResource resource, - String providerId, IScannerConfigBuilderInfo2 buildInfo, - IScannerInfoCollector collector) { - return invokeProvider(monitor, resource, new InfoContext(resource.getProject()), providerId, buildInfo, collector, null); - } + String providerId, IScannerConfigBuilderInfo2 buildInfo, + IScannerInfoCollector collector) { + return invokeProvider(monitor, resource, new InfoContext(resource.getProject()), providerId, buildInfo, collector, null); + } - @Override + @Override public boolean invokeProvider(IProgressMonitor monitor, - IResource resource, - InfoContext context, - String providerId, - IScannerConfigBuilderInfo2 buildInfo, - IScannerInfoCollector collector, - Properties env) { - // initialize fields - this.resource = resource; - this.providerId = providerId; - this.buildInfo = buildInfo; - this.collector = collector; + IResource resource, + InfoContext context, + String providerId, + IScannerConfigBuilderInfo2 buildInfo, + IScannerInfoCollector collector, + Properties env) { + // initialize fields + this.resource = resource; + this.providerId = providerId; + this.buildInfo = buildInfo; + this.collector = collector; - IProject currentProject = resource.getProject(); - // call a subclass to initialize protected fields - if (!initialize()) { - return false; - } - if (monitor == null) { - monitor = new NullProgressMonitor(); - } - monitor.beginTask(MakeMessages.getString("ExternalScannerInfoProvider.Reading_Specs"), 100); //$NON-NLS-1$ + IProject currentProject = resource.getProject(); + // call a subclass to initialize protected fields + if (!initialize()) { + return false; + } + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + monitor.beginTask(MakeMessages.getString("ExternalScannerInfoProvider.Reading_Specs"), 100); //$NON-NLS-1$ - try { + try { ILanguage language = context.getLanguage(); IConsole console; if (language!=null && isConsoleEnabled()) { @@ -114,23 +111,24 @@ public class DefaultRunSIProvider implements IExternalScannerInfoProvider { // that looks in extension points registry and won't find the id console = CCorePlugin.getDefault().getConsole(MakeCorePlugin.PLUGIN_ID + ".console.hidden"); //$NON-NLS-1$ } - console.start(currentProject); - OutputStream cos = console.getOutputStream(); + console.start(currentProject); + OutputStream cos = console.getOutputStream(); - // Before launching give visual cues via the monitor - monitor.subTask(MakeMessages.getString("ExternalScannerInfoProvider.Reading_Specs")); //$NON-NLS-1$ + // Before launching give visual cues via the monitor + monitor.subTask(MakeMessages.getString("ExternalScannerInfoProvider.Reading_Specs")); //$NON-NLS-1$ - String errMsg = null; - ICommandLauncher launcher = new CommandLauncher(); - launcher.setProject(currentProject); - // Print the command for visual interaction. - launcher.showCommand(true); + String errMsg = null; + ICommandLauncher launcher = new CommandLauncher(); + launcher.setProject(currentProject); + // Print the command for visual interaction. + launcher.showCommand(true); - String[] comandLineOptions = getCommandLineOptions(); - String params = coligate(comandLineOptions); + String[] comandLineOptions = getCommandLineOptions(); + IPath program = getCommandToLaunch(); + String params = coligate(comandLineOptions); - monitor.subTask(MakeMessages.getString("ExternalScannerInfoProvider.Invoking_Command") //$NON-NLS-1$ - + getCommandToLaunch() + params); + monitor.subTask(MakeMessages.getString("ExternalScannerInfoProvider.Invoking_Command") //$NON-NLS-1$ + + program + params); ErrorParserManager epm = new ErrorParserManager(currentProject, markerGenerator, new String[] {GMAKE_ERROR_PARSER_ID}); epm.setOutputStream(cos); @@ -140,90 +138,66 @@ public class DefaultRunSIProvider implements IExternalScannerInfoProvider { ConsoleOutputSniffer sniffer = ScannerInfoConsoleParserFactory.getESIProviderOutputSniffer( stdout, stderr, currentProject, context, providerId, buildInfo, collector, markerGenerator); - OutputStream consoleOut = (sniffer == null ? cos : sniffer.getOutputStream()); - OutputStream consoleErr = (sniffer == null ? cos : sniffer.getErrorStream()); - Process p = launcher.execute(getCommandToLaunch(), comandLineOptions, setEnvironment(launcher, env), fWorkingDirectory, monitor); - if (p != null) { - try { - // Close the input of the Process explicitely. - // We will never write to it. - p.getOutputStream().close(); - } catch (IOException e) { - } - if (launcher.waitAndRead(consoleOut, consoleErr, new SubProgressMonitor(monitor, 0)) != ICommandLauncher.OK) { - errMsg = launcher.getErrorMessage(); - } - monitor.subTask(MakeMessages.getString("ExternalScannerInfoProvider.Parsing_Output")); //$NON-NLS-1$ - } - else { - errMsg = launcher.getErrorMessage(); - } - - if (errMsg != null) { - String errorPrefix = MakeMessages.getString("ExternalScannerInfoProvider.Error_Prefix"); //$NON-NLS-1$ - String program = fCompileCommand.toString(); - - String msg = MakeMessages.getFormattedString(EXTERNAL_SI_PROVIDER_ERROR, program+params); - printLine(consoleErr, errorPrefix + msg + NEWLINE); - - // Launching failed, trying to figure out possible cause - Properties envMap = getEnvMap(launcher, env); - String envPath = envMap.getProperty(PATH_ENV); - if (envPath == null) { - envPath = System.getenv(PATH_ENV); + OutputStream consoleOut = (sniffer == null ? cos : sniffer.getOutputStream()); + OutputStream consoleErr = (sniffer == null ? cos : sniffer.getErrorStream()); + Process p = launcher.execute(program, comandLineOptions, setEnvironment(launcher, env), fWorkingDirectory, monitor); + if (p != null) { + try { + // Close the input of the Process explicitly. + // We will never write to it. + p.getOutputStream().close(); + } catch (IOException e) { } - if (!fCompileCommand.isAbsolute() && PathUtil.findProgramLocation(program, envPath) == null) { - printLine(consoleErr, errMsg); - msg = MakeMessages.getFormattedString("ExternalScannerInfoProvider.Working_Directory", fWorkingDirectory); //$NON-NLS-1$ - msg = MakeMessages.getFormattedString("ExternalScannerInfoProvider.Program_Not_In_Path", program); //$NON-NLS-1$ - printLine(consoleErr, errorPrefix + msg + NEWLINE); - printLine(consoleErr, PATH_ENV + "=[" + envPath + "]" + NEWLINE); //$NON-NLS-1$ //$NON-NLS-2$ - } else { - printLine(consoleErr, errorPrefix + errMsg); - msg = MakeMessages.getFormattedString("ExternalScannerInfoProvider.Working_Directory", fWorkingDirectory); //$NON-NLS-1$ - printLine(consoleErr, PATH_ENV + "=[" + envPath + "]" + NEWLINE); //$NON-NLS-1$ //$NON-NLS-2$ + if (launcher.waitAndRead(consoleOut, consoleErr, new SubProgressMonitor(monitor, 0)) != ICommandLauncher.OK) { + errMsg = launcher.getErrorMessage(); } - - monitor.subTask(MakeMessages.getString("ExternalScannerInfoProvider.Creating_Markers")); //$NON-NLS-1$ + monitor.subTask(MakeMessages.getString("ExternalScannerInfoProvider.Parsing_Output")); //$NON-NLS-1$ + } else { + errMsg = launcher.getErrorMessage(); } - consoleOut.close(); - consoleErr.close(); - cos.close(); - } - catch (Exception e) { - MakeCorePlugin.log(e); - } - finally { - monitor.done(); - } - return true; - } + if (errMsg != null) { + printLine(consoleErr, errMsg); + printLine(consoleErr, MakeMessages.getFormattedString("ExternalScannerInfoProvider.Provider_Error", program + params) + NEWLINE); //$NON-NLS-1$ + } - protected IPath getCommandToLaunch() { - return fCompileCommand; - } + consoleOut.close(); + consoleErr.close(); + cos.close(); + } + catch (Exception e) { + MakeCorePlugin.log(e); + } + finally { + monitor.done(); + } + return true; + } - protected String[] getCommandLineOptions() { - // add additional arguments - // subclass can change default behavior - return prepareArguments( - buildInfo.isUseDefaultProviderCommand(providerId)); - } + protected IPath getCommandToLaunch() { + return fCompileCommand; + } - private void printLine(OutputStream stream, String msg) throws IOException { - stream.write((msg + NEWLINE).getBytes()); - stream.flush(); - } + protected String[] getCommandLineOptions() { + // add additional arguments + // subclass can change default behavior + return prepareArguments( + buildInfo.isUseDefaultProviderCommand(providerId)); + } - /** - * Initialization of protected fields. - * Subclasses are most likely to override default implementation. - */ - protected boolean initialize() { + private void printLine(OutputStream stream, String msg) throws IOException { + stream.write((msg + NEWLINE).getBytes()); + stream.flush(); + } + + /** + * Initialization of protected fields. + * Subclasses are most likely to override default implementation. + */ + protected boolean initialize() { IProject currProject = resource.getProject(); - //fWorkingDirectory = resource.getProject().getLocation(); + //fWorkingDirectory = resource.getProject().getLocation(); URI workingDirURI = MakeBuilderUtil.getBuildDirectoryURI(currProject, MakeBuilder.BUILDER_ID); String pathString = EFSExtensionManager.getDefault().getPathFromURI(workingDirURI); if(pathString != null) { @@ -235,34 +209,34 @@ public class DefaultRunSIProvider implements IExternalScannerInfoProvider { throw new IllegalStateException(); } - fCompileCommand = new Path(buildInfo.getProviderRunCommand(providerId)); - fCompileArguments = ScannerConfigUtil.tokenizeStringWithQuotes(buildInfo.getProviderRunArguments(providerId), "\"");//$NON-NLS-1$ - return (fCompileCommand != null); - } + fCompileCommand = new Path(buildInfo.getProviderRunCommand(providerId)); + fCompileArguments = ScannerConfigUtil.tokenizeStringWithQuotes(buildInfo.getProviderRunArguments(providerId), "\"");//$NON-NLS-1$ + return (fCompileCommand != null); + } - /** - * Add additional arguments. For example: tso - target specific options - * Base class implementation returns compileArguments. - * Subclasses are most likely to override default implementation. - */ - protected String[] prepareArguments(boolean isDefaultCommand) { - return fCompileArguments; - } + /** + * Add additional arguments. For example: tso - target specific options + * Base class implementation returns compileArguments. + * Subclasses are most likely to override default implementation. + */ + protected String[] prepareArguments(boolean isDefaultCommand) { + return fCompileArguments; + } - private String coligate(String[] array) { - StringBuffer sb = new StringBuffer(128); - for (int i = 0; i < array.length; ++i) { - sb.append(' '); - sb.append(array[i]); - } - String ca = sb.toString(); - return ca; - } + private String coligate(String[] array) { + StringBuffer sb = new StringBuffer(128); + for (int i = 0; i < array.length; ++i) { + sb.append(' '); + sb.append(array[i]); + } + String ca = sb.toString(); + return ca; + } private Properties getEnvMap(ICommandLauncher launcher, Properties initialEnv) { // Set the environmennt, some scripts may need the CWD var to be set. Properties props = initialEnv != null ? initialEnv : launcher.getEnvironment(); - + if (fWorkingDirectory != null) { props.put("CWD", fWorkingDirectory.toOSString()); //$NON-NLS-1$ props.put("PWD", fWorkingDirectory.toOSString()); //$NON-NLS-1$ @@ -278,20 +252,20 @@ public class DefaultRunSIProvider implements IExternalScannerInfoProvider { return props; } - protected String[] setEnvironment(ICommandLauncher launcher, Properties initialEnv) { - Properties props = getEnvMap(launcher, initialEnv); - String[] env = null; - ArrayList envList = new ArrayList(); - Enumeration names = props.propertyNames(); - if (names != null) { - while (names.hasMoreElements()) { - String key = (String) names.nextElement(); - envList.add(key + "=" + props.getProperty(key)); //$NON-NLS-1$ - } - env = envList.toArray(new String[envList.size()]); - } - return env; - } + protected String[] setEnvironment(ICommandLauncher launcher, Properties initialEnv) { + Properties props = getEnvMap(launcher, initialEnv); + String[] env = null; + ArrayList envList = new ArrayList(); + Enumeration names = props.propertyNames(); + if (names != null) { + while (names.hasMoreElements()) { + String key = (String) names.nextElement(); + envList.add(key + "=" + props.getProperty(key)); //$NON-NLS-1$ + } + env = envList.toArray(new String[envList.size()]); + } + return env; + } /** diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ExternalBuildRunner.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ExternalBuildRunner.java index 5d790aaa629..ad406199f85 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ExternalBuildRunner.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ExternalBuildRunner.java @@ -53,7 +53,6 @@ import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider; import org.eclipse.cdt.newmake.internal.core.StreamMonitor; import org.eclipse.cdt.utils.CommandLineUtil; import org.eclipse.cdt.utils.EFSExtensionManager; -import org.eclipse.cdt.utils.PathUtil; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -221,29 +220,12 @@ public class ExternalBuildRunner extends AbstractBuildRunner { } catch (CoreException e) { } } else { - buf = new StringBuffer(launcher.getCommandLine()).append(NEWLINE); errMsg = launcher.getErrorMessage(); } project.setSessionProperty(qName, !monitor.isCanceled() && !isClean ? new Integer(streamMon.getWorkDone()) : null); if (errMsg != null) { - // Launching failed, trying to figure out possible cause - String errorPrefix = ManagedMakeMessages.getResourceString("ManagedMakeBuilder.error.prefix"); //$NON-NLS-1$ - String buildCommandStr = buildCommand.toString(); - String envPath = envMap.get(PATH_ENV); - if (envPath==null) { - envPath = System.getenv(PATH_ENV); - } - if (PathUtil.findProgramLocation(buildCommandStr, envPath)==null) { - buf.append(errMsg).append(NEWLINE); - errMsg = ManagedMakeMessages.getFormattedString("ManagedMakeBuilder.message.program.not.in.path", buildCommandStr); //$NON-NLS-1$ - buf.append(errorPrefix).append(errMsg).append(NEWLINE); - buf.append(NEWLINE); - buf.append(PATH_ENV+"=["+envPath+"]").append(NEWLINE); //$NON-NLS-1$//$NON-NLS-2$ - } else { - buf.append(errorPrefix).append(errMsg).append(NEWLINE); - } - consoleErr.write(buf.toString().getBytes()); + consoleErr.write(errMsg.getBytes()); consoleErr.flush(); } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java index b0a23fdb090..f4fbfd0244a 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Intel Corporation and others. + * Copyright (c) 2006, 2012 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 @@ -20,14 +20,9 @@ import java.util.Set; import org.eclipse.cdt.core.CommandLauncher; import org.eclipse.cdt.core.ICommandLauncher; -import org.eclipse.cdt.internal.core.Cygwin; import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand; -import org.eclipse.cdt.managedbuilder.internal.core.ManagedMakeMessages; -import org.eclipse.cdt.utils.PathUtil; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubProgressMonitor; /** @@ -48,44 +43,6 @@ public class CommandBuilder implements IBuildModelBuilder { private Process fProcess; private String fErrMsg; - private class CommandSearchLauncher extends CommandLauncher { - @Override - protected String[] constructCommandArray(String command, String[] commandArgs) { - String[] args = new String[1 + commandArgs.length]; - if (Platform.getOS().equals(Platform.OS_WIN32)) { - // find a location of the executable - String envPathValue = fCmd.getEnvironment().get(PATH_ENV); - IPath location = PathUtil.findProgramLocation(command, envPathValue); - if(location != null) { - try { - // Handle cygwin link - command = Cygwin.cygwinToWindowsPath(location.toString(), envPathValue); - } catch (Exception e) { - command = location.toString(); - } - } - //if not found, continue with the command passed as an argument - } - - args[0] = command; - System.arraycopy(commandArgs, 0, args, 1, commandArgs.length); - return args; - } - - @Override - protected void printCommandLine(OutputStream os) { - if (os != null) { - String cmd = CommandBuilder.this.getCommandLine(); - try { - os.write(cmd.getBytes()); - os.flush(); - } catch (IOException e) { - // ignore; - } - } - } - } - protected class OutputStreamWrapper extends OutputStream { private OutputStream fOut; @@ -131,9 +88,7 @@ public class CommandBuilder implements IBuildModelBuilder { * @see org.eclipse.cdt.managedbuilder.internal.builddescription.IBuildDescriptionBuilder#build(java.io.OutputStream, java.io.OutputStream, org.eclipse.core.runtime.IProgressMonitor) */ @Override - public int build(OutputStream out, OutputStream err, - IProgressMonitor monitor){ - + public int build(OutputStream out, OutputStream err, IProgressMonitor monitor){ //TODO: should we display the command line here? monitor.beginTask("", getNumCommands()); //$NON-NLS-1$ monitor.subTask(""/*getCommandLine()*/); //$NON-NLS-1$ @@ -153,17 +108,18 @@ public class CommandBuilder implements IBuildModelBuilder { return STATUS_ERROR_LAUNCH; } + int st = ICommandLauncher.ILLEGAL_COMMAND; if (fProcess != null) { try { // Close the input of the process since we will never write to it fProcess.getOutputStream().close(); } catch (IOException e) { } + //wrapping out and err streams to avoid their closure + st = launcher.waitAndRead(wrap(out), wrap(err), + new SubProgressMonitor(monitor, getNumCommands())); } - //wrapping out and err streams to avoid their closure - int st = launcher.waitAndRead(wrap(out), wrap(err), - new SubProgressMonitor(monitor, getNumCommands())); switch(st){ case ICommandLauncher.OK: if(fProcess.exitValue() != 0) @@ -184,19 +140,7 @@ public class CommandBuilder implements IBuildModelBuilder { if(DbgUtil.DEBUG) DbgUtil.trace("error launching the command: " + fErrMsg); //$NON-NLS-1$ - String program = fCmd.getCommand().toOSString(); - String envPath = fCmd.getEnvironment().get(PATH_ENV); - if (envPath==null) { - envPath = System.getenv(PATH_ENV); - } - if (PathUtil.findProgramLocation(program, envPath)==null) { - printMessage(fErrMsg, out); - String errMsg = ManagedMakeMessages.getFormattedString("ManagedMakeBuilder.message.program.not.in.path", program); //$NON-NLS-1$ - printErrorMessage(errMsg + NEWLINE, out); - printMessage(null, PATH_ENV+"=["+envPath+"]", out); //$NON-NLS-1$//$NON-NLS-2$ - } else { - printErrorMessage(fErrMsg, out); - } + printMessage(fErrMsg, out); break; } @@ -205,12 +149,10 @@ public class CommandBuilder implements IBuildModelBuilder { } protected ICommandLauncher createLauncher() { -// if(isWindows()) -// return new CommandLauncher(); - return new CommandSearchLauncher(); + return new CommandLauncher(); } - public String getErrMsg(){ + public String getErrMsg() { return fErrMsg; } @@ -228,14 +170,10 @@ public class CommandBuilder implements IBuildModelBuilder { return list.toArray(new String[list.size()]); } - private void printMessage(String prefix, String msg, OutputStream os){ + protected void printMessage(String msg, OutputStream os){ if (os != null) { - if (prefix==null) { - prefix=""; //$NON-NLS-1$ - } - msg = prefix + msg + NEWLINE; try { - os.write(msg.getBytes()); + os.write((msg + NEWLINE).getBytes()); os.flush(); } catch (IOException e) { // ignore; @@ -244,22 +182,6 @@ public class CommandBuilder implements IBuildModelBuilder { } - protected void printMessage(String msg, OutputStream os){ - if (os != null) { - msg = ManagedMakeMessages.getFormattedString("InternalBuilder.msg.header", msg); //$NON-NLS-1$ - printMessage(null, msg, os); - } - - } - - private void printErrorMessage(String msg, OutputStream os){ - if (os != null) { - String errorPrefix = ManagedMakeMessages.getResourceString("ManagedMakeBuilder.error.prefix"); //$NON-NLS-1$ - printMessage(errorPrefix, msg, os); - } - - } - public int getNumCommands() { return 1; } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java index 5446824dae3..1650ca25c24 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Rational Software - Initial API and implementation *******************************************************************************/ @@ -74,10 +74,10 @@ import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; /** - * This is the incremental builder associated with a managed build project. It dynamically + * This is the incremental builder associated with a managed build project. It dynamically * decides the makefile generator it wants to use for a specific target. - * - * @since 1.2 + * + * @since 1.2 */ public class GeneratedMakefileBuilder extends ACBuilder { /** @@ -89,7 +89,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { private boolean incrBuildNeeded = false; private boolean fullBuildNeeded = false; private List reservedNames; - + public ResourceDeltaVisitor(IManagedBuildInfo info) { buildInfo = info; String ext = buildInfo.getBuildArtifactExtension(); @@ -103,7 +103,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { info.getDefaultConfiguration()); } catch (BuildMacroException e){ } - + String name = buildInfo.getBuildArtifactName(); //try to resolve build macros in the build artifact name try{ @@ -140,13 +140,13 @@ public class GeneratedMakefileBuilder extends ACBuilder { } private boolean isProjectFile(IResource resource) { - return reservedNames.contains(resource.getName()); + return reservedNames.contains(resource.getName()); } public boolean shouldBuildIncr() { return incrBuildNeeded; } - + public boolean shouldBuildFull() { return fullBuildNeeded; } @@ -158,15 +158,15 @@ public class GeneratedMakefileBuilder extends ACBuilder { if (resource != null && resource.getProject() == getProject()) { switch(resource.getType()){ case IResource.FILE: - String name = resource.getName(); + String name = resource.getName(); if ((!name.equals(buildGoalName) && // TODO: Also need to check for secondary outputs - (resource.isDerived() || + (resource.isDerived() || (isProjectFile(resource)) || (isGeneratedResource(resource))))) { - // The resource that changed has attributes which make it uninteresting, + // The resource that changed has attributes which make it uninteresting, // so don't do anything - } + } else { // TODO: Should we do extra checks here to determine if a build is really needed, // or do you just do exclusion checks like above? @@ -180,15 +180,15 @@ public class GeneratedMakefileBuilder extends ACBuilder { // o An Option // o An AdditionalInput // - //if (resourceName.equals(buildGoalName) || + //if (resourceName.equals(buildGoalName) || // (buildInfo.buildsFileType(ext) || buildInfo.isHeaderFile(ext))) { - + // We need to do an incremental build, at least incrBuildNeeded = true; if (delta.getKind() == IResourceDelta.REMOVED) { // If a meaningful resource was removed, then force a full build // This is required because an incremental build will trigger make to - // do nothing for a missing source, since the state after the file + // do nothing for a missing source, since the state after the file // removal is uptodate, as far as make is concerned // A full build will clean, and ultimately trigger a relink without // the object generated from the deleted source, which is what we want @@ -197,9 +197,9 @@ public class GeneratedMakefileBuilder extends ACBuilder { // decided to do a full build anyway break; } - + //} - } + } return false; } @@ -213,14 +213,14 @@ public class GeneratedMakefileBuilder extends ACBuilder { IConfiguration configs[]; Configuration otherConfigs[]; int resourceChangeState; - + private static final IPath[] ignoreList = { new Path(".cdtproject"), //$NON-NLS-1$ new Path(".cproject"), //$NON-NLS-1$ new Path(".cdtbuild"), //$NON-NLS-1$ new Path(".settings"), //$NON-NLS-1$ }; - + OtherConfigVerifier(IConfiguration cfg){ config = cfg; configs = cfg.getManagedProject().getConfigurations(); @@ -231,10 +231,10 @@ public class GeneratedMakefileBuilder extends ACBuilder { otherConfigs[counter++] = (Configuration)configs[i]; } } - + @Override public boolean visit(IResourceDelta delta) throws CoreException { - + IResource rc = delta.getResource(); if(rc.getType() == IResource.FILE){ if(isResourceValuable(rc)) @@ -243,7 +243,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { } return !isGeneratedForConfig(rc, config) && isResourceValuable(rc); } - + public void updateOtherConfigs(IResourceDelta delta){ if(delta == null) resourceChangeState = ~0; @@ -254,16 +254,16 @@ public class GeneratedMakefileBuilder extends ACBuilder { resourceChangeState = ~0; } } - + setResourceChangeStateForOtherConfigs(); } - + private void setResourceChangeStateForOtherConfigs(){ for(int i = 0; i < otherConfigs.length; i++){ otherConfigs[i].addResourceChangeState(resourceChangeState); } } - + private boolean isGeneratedForConfig(IResource resource, IConfiguration cfg) { // Is this a generated directory ... IPath path = resource.getProjectRelativePath(); @@ -308,7 +308,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { private static final String TYPE_REBUILD = "ManagedMakeBuider.type.rebuild"; //$NON-NLS-1$ private static final String INTERNAL_BUILDER = "ManagedMakeBuilder.message.internal.builder"; //$NON-NLS-1$ public static boolean VERBOSE = false; - + // Local variables protected Vector generationProblems; protected IProject[] referencedProjects; @@ -365,7 +365,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { } else { consoleHeader[0] = new String(); outputError(getProject().getName(), "The given build type is not supported in this context"); //$NON-NLS-1$ - } + } consoleHeader[1] = configName; consoleHeader[2] = getProject().getName(); buf.append(NEWLINE); @@ -379,20 +379,20 @@ public class GeneratedMakefileBuilder extends ACBuilder { // Throw the exception back to the builder throw e; } catch (IOException io) { // Ignore console failures... - } + } } /** - * + * * This method has been created so that subclasses can override how the builder obtains its * build info. The default implementation retrieves the info from the build manager. - * + * * @return An IManagedBuildInfo object representing the build info. */ protected IManagedBuildInfo getBuildInfo() { return ManagedBuildManager.getBuildInfo(getProject()); } - + /* (non-Javadoc) * @see org.eclipse.core.internal.events.InternalBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor) */ @@ -423,7 +423,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { } else { cfgs = new IConfiguration[] {info.getDefaultConfiguration() }; } - + for (IConfiguration cfg : cfgs) { updateOtherConfigs(cfg, kind); @@ -455,7 +455,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { if(delta == null) fullBuildNeeded = true; if(cfg.needsRebuild() || delta != null){ - //use a build description model to calculate the resources to be cleaned + //use a build description model to calculate the resources to be cleaned //only in case there are some changes to the project sources or build information try{ int flags = BuildDescriptionManager.REBUILD | BuildDescriptionManager.DEPFILES | BuildDescriptionManager.DEPS; @@ -535,7 +535,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { // Should only build this project once, for this delta break; } else { - int refKind = refDelta.getKind(); + int refKind = refDelta.getKind(); if (refKind != IResourceDelta.NO_CHANGE) { int refFlags = refDelta.getFlags(); if (!(refKind == IResourceDelta.CHANGED && @@ -546,7 +546,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { break; } } - } + } } } } @@ -561,11 +561,11 @@ public class GeneratedMakefileBuilder extends ACBuilder { private void updateOtherConfigs(IConfiguration cfg, int buildKind){ new OtherConfigVerifier(cfg).updateOtherConfigs(buildKind == FULL_BUILD ? null : getDelta(getProject())); } - + /** - * Check whether the build has been canceled. Cancellation requests + * Check whether the build has been canceled. Cancellation requests * propagated to the caller by throwing OperationCanceledException. - * + * * @see org.eclipse.core.runtime.OperationCanceledException#OperationCanceledException() */ public void checkCancel(IProgressMonitor monitor) { @@ -602,7 +602,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { outputError(buildDir == null ? "null" : buildDir.getName(), "Could not delete the build directory"); //$NON-NLS-1$ //$NON-NLS-2$ return; } - String status; + String status; try { // try the brute force approach first status = ManagedMakeMessages.getFormattedString("ManagedMakeBuilder.message.clean.deleting.output", buildDir.getName()); //$NON-NLS-1$ @@ -635,9 +635,9 @@ public class GeneratedMakefileBuilder extends ACBuilder { IManagedBuilderMakefileGenerator generator = ManagedBuildManager.getBuildfileGenerator(info.getDefaultConfiguration()); generator.initialize(getProject(), info, monitor); cleanBuild(info, generator, monitor); - } catch (IOException io) {} // Ignore console failures... + } catch (IOException io) {} // Ignore console failures... } - + /* (non-Javadoc) * @param info * @param generator @@ -649,11 +649,11 @@ public class GeneratedMakefileBuilder extends ACBuilder { if (buildDir == null) { buildDir = new Path(info.getConfigurationName()); } - IPath makefilePath = getProject().getLocation().append(buildDir.append(generator.getMakefileName())); + IPath makefilePath = getProject().getLocation().append(buildDir.append(generator.getMakefileName())); IWorkspaceRoot root = CCorePlugin.getWorkspace().getRoot(); IFile makefile = root.getFileForLocation(makefilePath); - - if (makefile != null && makefile.isAccessible()) { + + if (makefile != null && makefile.isAccessible()) { // invoke make with the clean argument String statusMsg = ManagedMakeMessages.getFormattedString("ManagedMakeBuilder.message.starting", getProject().getName()); //$NON-NLS-1$ monitor.subTask(statusMsg); @@ -672,14 +672,14 @@ public class GeneratedMakefileBuilder extends ACBuilder { if (monitor == null) { monitor = new NullProgressMonitor(); } - + checkCancel(monitor); //If the previous builder invocation was cancelled, generated files might be corrupted - //in case one or more of the generated makefiles (e.g. dep files) are corrupted, - //the builder invocation might fail because of the possible syntax errors, so e.g. "make clean" will not work + //in case one or more of the generated makefiles (e.g. dep files) are corrupted, + //the builder invocation might fail because of the possible syntax errors, so e.g. "make clean" will not work //we need to explicitly clean the generated directories // clean(new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN)); - + // Regenerate the makefiles for this project checkCancel(monitor); String statusMsg = ManagedMakeMessages.getFormattedString("ManagedMakeBuilder.message.rebuild.makefiles", getProject().getName()); //$NON-NLS-1$ @@ -691,26 +691,26 @@ public class GeneratedMakefileBuilder extends ACBuilder { IStatus[] kids = result.getChildren(); for (int index = 0; index < kids.length; ++index) { // One possibility is that there is nothing to build - IStatus status = kids[index]; + IStatus status = kids[index]; if (status.getCode() == IManagedBuilderMakefileGenerator.NO_SOURCE_FOLDERS) { // Inform the user, via the console, that there is nothing to build // either because there are no buildable sources files or all potentially // buildable files have been excluded from build - try { + try { emitNoSourceMessage(FULL_BUILD, status, info.getConfigurationName()); } catch (CoreException e) { // Throw the exception back to the builder throw e; - } + } // Dude, we're done return; } else { // Stick this in the list of stuff to warn the user about - getGenerationProblems().add(status); - } + getGenerationProblems().add(status); + } } } - + // Now call make checkCancel(monitor); statusMsg = ManagedMakeMessages.getFormattedString("ManagedMakeBuilder.message.starting", getProject().getName()); //$NON-NLS-1$ @@ -719,11 +719,11 @@ public class GeneratedMakefileBuilder extends ACBuilder { if (topBuildDir != null) { invokeMake(FULL_BUILD, topBuildDir, info, generator, monitor); } else { - statusMsg = ManagedMakeMessages.getFormattedString(NOTHING_BUILT, getProject().getName()); + statusMsg = ManagedMakeMessages.getFormattedString(NOTHING_BUILT, getProject().getName()); monitor.subTask(statusMsg); return; } - + // Now regenerate the dependencies checkCancel(monitor); statusMsg = ManagedMakeMessages.getFormattedString("ManagedMakeBuilder.message.regen.deps", getProject().getName()); //$NON-NLS-1$ @@ -736,12 +736,12 @@ public class GeneratedMakefileBuilder extends ACBuilder { } // Build finished message - statusMsg = ManagedMakeMessages.getFormattedString(BUILD_FINISHED, getProject().getName()); + statusMsg = ManagedMakeMessages.getFormattedString(BUILD_FINISHED, getProject().getName()); monitor.subTask(statusMsg); } - + /* (non-Javadoc) - * + * * @return */ private Vector getGenerationProblems() { @@ -750,11 +750,11 @@ public class GeneratedMakefileBuilder extends ACBuilder { } return generationProblems; } - + /* (non-javadoc) * Answers an array of strings with the proper make targets - * for a build with no custom prebuild/postbuild steps - * + * for a build with no custom prebuild/postbuild steps + * * @param fullBuild * @return */ @@ -771,7 +771,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { } return args.toArray(new String[args.size()]); } - + protected List getResourcesToBuild() { if (resourcesToBuild == null) { resourcesToBuild = new ArrayList(); @@ -797,7 +797,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { if (monitor == null) { monitor = new NullProgressMonitor(); } - + // Ask the makefile generator to generate any makefiles needed to build delta checkCancel(monitor); String statusMsg = ManagedMakeMessages.getFormattedString("ManagedMakeBuilder.message.update.makefiles", getProject().getName()); //$NON-NLS-1$ @@ -807,23 +807,23 @@ public class GeneratedMakefileBuilder extends ACBuilder { IStatus[] kids = result.getChildren(); for (int index = 0; index < kids.length; ++index) { // One possibility is that there is nothing to build - IStatus status = kids[index]; + IStatus status = kids[index]; if (status.getCode() == IManagedBuilderMakefileGenerator.NO_SOURCE_FOLDERS) { // Inform the user, via the console, that there is nothing to build // either because there are no buildable sources files or all potentially // buildable files have been excluded from build - try { + try { emitNoSourceMessage(INCREMENTAL_BUILD, status, info.getConfigurationName()); } catch (CoreException e) { // Throw the exception back to the builder throw e; - } + } // Dude, we're done return; } else { // Stick this in the list of stuff to warn the user about - getGenerationProblems().add(status); - } + getGenerationProblems().add(status); + } } } @@ -835,11 +835,11 @@ public class GeneratedMakefileBuilder extends ACBuilder { if (buildDir != null) { invokeMake(INCREMENTAL_BUILD, buildDir, info, generator, monitor); } else { - statusMsg = ManagedMakeMessages.getFormattedString(NOTHING_BUILT, getProject().getName()); + statusMsg = ManagedMakeMessages.getFormattedString(NOTHING_BUILT, getProject().getName()); monitor.subTask(statusMsg); return; } - + // Generate the dependencies for all changes checkCancel(monitor); statusMsg = ManagedMakeMessages.getFormattedString("ManagedMakeBuilder.message.updating.deps", getProject().getName()); //$NON-NLS-1$ @@ -849,17 +849,17 @@ public class GeneratedMakefileBuilder extends ACBuilder { } catch (CoreException e) { throw e; } - + // Build finished message - statusMsg = ManagedMakeMessages.getFormattedString(BUILD_FINISHED, getProject().getName()); + statusMsg = ManagedMakeMessages.getFormattedString(BUILD_FINISHED, getProject().getName()); monitor.subTask(statusMsg); } /* (non-Javadoc) - * @param buildType + * @param buildType * @param buildDir * @param info - * @param generator + * @param generator * @param monitor */ protected void invokeMake(int buildType, IPath buildDir, IManagedBuildInfo info, IManagedBuilderMakefileGenerator generator, IProgressMonitor monitor) { @@ -870,13 +870,13 @@ public class GeneratedMakefileBuilder extends ACBuilder { } try { - // Figure out the working directory for the build and make sure there is a makefile there + // Figure out the working directory for the build and make sure there is a makefile there final URI workingDirectoryURI = getProject().getFolder(buildDir).getLocationURI(); final String pathFromURI = EFSExtensionManager.getDefault().getPathFromURI(workingDirectoryURI); if(pathFromURI == null) { throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, ManagedMakeMessages.getString("ManagedMakeBuilder.message.error"), null)); //$NON-NLS-1$ } - + IPath workingDirectory = new Path(pathFromURI); IWorkspace workspace = currentProject.getWorkspace(); @@ -889,7 +889,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { } IPath makefile = workingDirectory.append(generator.getMakefileName()); if (root.getFileForLocation(makefile) == null) { - return; + return; } // Flag to the user that make is about to be called @@ -907,7 +907,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { } catch (BuildMacroException e){ } - IPath makeCommand = new Path(makeCmd); + IPath makeCommand = new Path(makeCmd); String[] msgs = new String[2]; msgs[0] = makeCommand.toString(); msgs[1] = currentProject.getName(); @@ -928,13 +928,13 @@ public class GeneratedMakefileBuilder extends ACBuilder { consoleHeader[0] = ManagedMakeMessages.getResourceString(TYPE_CLEAN); break; } - + consoleHeader[1] = info.getConfigurationName(); consoleHeader[2] = currentProject.getName(); buf.append(NEWLINE); buf.append(ManagedMakeMessages.getFormattedString(CONSOLE_HEADER, consoleHeader)).append(NEWLINE); buf.append(NEWLINE); - + IConfiguration cfg = info.getDefaultConfiguration(); if(!cfg.isSupported()){ String msg = ManagedMakeMessages.getFormattedString(WARNING_UNSUPPORTED_CONFIGURATION,new String[] {cfg.getName(),cfg.getToolChain().getName()}); @@ -943,10 +943,10 @@ public class GeneratedMakefileBuilder extends ACBuilder { } consoleOutStream.write(buf.toString().getBytes()); consoleOutStream.flush(); - + // Remove all markers for this project removeAllMarkers(currentProject); - + // Get a launcher for the make command String errMsg = null; IBuilder builder = info.getDefaultConfiguration().getBuilder(); @@ -964,20 +964,20 @@ public class GeneratedMakefileBuilder extends ACBuilder { } env = envList.toArray(new String[envList.size()]); } - + // Hook up an error parser manager - String[] errorParsers = info.getDefaultConfiguration().getErrorParserList(); + String[] errorParsers = info.getDefaultConfiguration().getErrorParserList(); ErrorParserManager epm = new ErrorParserManager(getProject(), workingDirectoryURI, this, errorParsers); epm.setOutputStream(consoleOutStream); // This variable is necessary to ensure that the EPM stream stay open // until we explicitly close it. See bug#123302. OutputStream epmOutputStream = epm.getOutputStream(); - - // Get the arguments to be passed to make from build model + + // Get the arguments to be passed to make from build model ArrayList makeArgs = new ArrayList(); String arg = info.getBuildArguments(); if (arg.length() > 0) { - String[] args = arg.split("\\s"); //$NON-NLS-1$ + String[] args = arg.split("\\s"); //$NON-NLS-1$ for (int i = 0; i < args.length; ++i) { makeArgs.add(args[i]); } @@ -1005,14 +1005,14 @@ public class GeneratedMakefileBuilder extends ACBuilder { String[] premakeTargets; switch (buildType) { case INCREMENTAL_BUILD: { - // For an incremental build with a prebuild step: - // Check the status of the main build with "make -q main-build" - // If up to date: - // then: don't invoke the prebuild step, which should be run only if - // something needs to be built in the main build - // else: invoke the prebuild step and the main build step - premakeArgs.add("-q"); //$NON-NLS-1$ - premakeArgs.add("main-build"); //$NON-NLS-1$ + // For an incremental build with a prebuild step: + // Check the status of the main build with "make -q main-build" + // If up to date: + // then: don't invoke the prebuild step, which should be run only if + // something needs to be built in the main build + // else: invoke the prebuild step and the main build step + premakeArgs.add("-q"); //$NON-NLS-1$ + premakeArgs.add("main-build"); //$NON-NLS-1$ premakeTargets = premakeArgs.toArray(new String[premakeArgs.size()]); proc = launcher.execute(makeCommand, premakeTargets, env, workingDirectory, monitor); if (proc != null) { @@ -1032,11 +1032,11 @@ public class GeneratedMakefileBuilder extends ACBuilder { if ((errMsg != null && errMsg.length() > 0) || proc == null) { // Can't tell if the build is needed, so assume it is, and let any errors be triggered - // when the "real" build is invoked below - makeArgs.add("pre-build"); //$NON-NLS-1$ - makeArgs.add("main-build"); //$NON-NLS-1$ + // when the "real" build is invoked below + makeArgs.add("pre-build"); //$NON-NLS-1$ + makeArgs.add("main-build"); //$NON-NLS-1$ } else { - // The "make -q" command launch was successful + // The "make -q" command launch was successful if (proc.exitValue() == 0) { // If the status value returned from "make -q" is 0, then the build state is up-to-date isuptodate = true; @@ -1045,40 +1045,40 @@ public class GeneratedMakefileBuilder extends ACBuilder { buf = new StringBuffer(); buf.append(NEWLINE); buf.append(uptodateMsg).append(NEWLINE); - // Write message on the console + // Write message on the console consoleOutStream.write(buf.toString().getBytes()); consoleOutStream.flush(); epmOutputStream.close(); consoleOutStream.close(); } else { // The status value was other than 0, so press on with the build process - makeArgs.add("pre-build"); //$NON-NLS-1$ - makeArgs.add("main-build"); //$NON-NLS-1$ + makeArgs.add("pre-build"); //$NON-NLS-1$ + makeArgs.add("main-build"); //$NON-NLS-1$ } } break; } case FULL_BUILD: { -// makeArgs.add("clean"); //$NON-NLS-1$ - makeArgs.add("pre-build"); //$NON-NLS-1$ - makeArgs.add("main-build"); //$NON-NLS-1$ +// makeArgs.add("clean"); //$NON-NLS-1$ + makeArgs.add("pre-build"); //$NON-NLS-1$ + makeArgs.add("main-build"); //$NON-NLS-1$ break; } case CLEAN_BUILD: { - makeArgs.add("clean"); //$NON-NLS-1$ + makeArgs.add("clean"); //$NON-NLS-1$ break; } } } else { - // No prebuild step - // + // No prebuild step + // makeArgs.addAll(Arrays.asList(getMakeTargets(buildType))); } makeTargets = makeArgs.toArray(new String[makeArgs.size()]); - // Launch make - main invocation + // Launch make - main invocation if (!isuptodate) { proc = launcher.execute(makeCommand, makeTargets, env, workingDirectory, monitor); if (proc != null) { @@ -1093,7 +1093,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { IProgressMonitor.UNKNOWN)); if(state != ICommandLauncher.OK){ errMsg = launcher.getErrorMessage(); - + if(state == ICommandLauncher.COMMAND_CANCELED){ //TODO: the better way of handling cancel is needed //currently the rebuild state is set to true forcing the full rebuild @@ -1102,14 +1102,14 @@ public class GeneratedMakefileBuilder extends ACBuilder { } } - // Force a resync of the projects without allowing the user to cancel. - // This is probably unkind, but short of this there is no way to insure - // the UI is up-to-date with the build results + // Force a resync of the projects without allowing the user to cancel. + // This is probably unkind, but short of this there is no way to insure + // the UI is up-to-date with the build results monitor.subTask(ManagedMakeMessages .getResourceString(REFRESH)); try { //currentProject.refreshLocal(IResource.DEPTH_INFINITE, null); - + // use the refresh scope manager to refresh RefreshScopeManager refreshManager = RefreshScopeManager.getInstance(); IWorkspaceRunnable runnable = refreshManager.getRefreshRunnable(currentProject); @@ -1122,25 +1122,23 @@ public class GeneratedMakefileBuilder extends ACBuilder { errMsg = launcher.getErrorMessage(); } - // Report either the success or failure of our mission + // Report either the success or failure of our mission buf = new StringBuffer(); if (errMsg != null && errMsg.length() > 0) { - String errorDesc = ManagedMakeMessages.getResourceString(BUILD_ERROR); - buf.append(errorDesc).append(NEWLINE); - buf.append("(").append(errMsg).append(")"); //$NON-NLS-1$ //$NON-NLS-2$ + buf.append(errMsg).append(NEWLINE); } else { - // Report a successful build + // Report a successful build String successMsg = ManagedMakeMessages.getFormattedString(BUILD_FINISHED, currentProject.getName()); buf.append(successMsg).append(NEWLINE); } - // Write message on the console + // Write message on the console consoleOutStream.write(buf.toString().getBytes()); consoleOutStream.flush(); epmOutputStream.close(); - // Generate any error markers that the build has discovered + // Generate any error markers that the build has discovered monitor.subTask(ManagedMakeMessages.getResourceString(MARKERS)); addBuilderMarkers(epm); consoleOutStream.close(); @@ -1154,8 +1152,8 @@ public class GeneratedMakefileBuilder extends ACBuilder { /* (non-Javadoc) * Removes the IMarkers for the project specified in the argument if the - * project exists, and is open. - * + * project exists, and is open. + * * @param project */ private void removeAllMarkers(IProject project) { @@ -1179,31 +1177,31 @@ public class GeneratedMakefileBuilder extends ACBuilder { } } } - + /** * called to invoke the MBS Internal Builder for building the given configuration - * + * * @param cfg configuration to be built * @param buildIncrementaly if true, incremental build will be performed, * only files that need rebuild will be built. * If false, full rebuild will be performed * @param resumeOnErr if true, build will continue in case of error while building. - * If false the build will stop on the first error + * If false the build will stop on the first error * @param monitor monitor */ - protected void invokeInternalBuilder(IConfiguration cfg, + protected void invokeInternalBuilder(IConfiguration cfg, boolean buildIncrementaly, boolean resumeOnErr, IProgressMonitor monitor) { - + boolean isParallel = ((Configuration)cfg).getParallelDef(); - + // Get the project and make sure there's a monitor to cancel the build IProject currentProject = cfg.getOwner().getProject(); if (monitor == null) { monitor = new NullProgressMonitor(); } - + String[] msgs = new String[2]; msgs[0] = ManagedMakeMessages.getResourceString(INTERNAL_BUILDER); msgs[1] = currentProject.getName(); @@ -1214,14 +1212,14 @@ public class GeneratedMakefileBuilder extends ACBuilder { try { int flags = 0; IResourceDelta delta = null; - + if(buildIncrementaly){ flags = BuildDescriptionManager.REBUILD | BuildDescriptionManager.REMOVED | BuildDescriptionManager.DEPS; delta = getDelta(currentProject); } - + IBuildDescription des = BuildDescriptionManager.createBuildDescription(cfg, delta, flags); - + DescriptionBuilder builder = null; if (!isParallel) builder = new DescriptionBuilder(des, buildIncrementaly, resumeOnErr, null); @@ -1236,16 +1234,16 @@ public class GeneratedMakefileBuilder extends ACBuilder { consoleHeader[0] = ManagedMakeMessages.getResourceString(TYPE_INC); else consoleHeader[0] = ManagedMakeMessages.getResourceString(TYPE_REBUILD); - + consoleHeader[1] = cfg.getName(); consoleHeader[2] = currentProject.getName(); buf.append(NEWLINE); buf.append(ManagedMakeMessages.getFormattedString(CONSOLE_HEADER, consoleHeader)).append(NEWLINE); buf.append(NEWLINE); - + buf.append(ManagedMakeMessages.getResourceString(INTERNAL_BUILDER_HEADER_NOTE)); buf.append("\n"); //$NON-NLS-1$ - + if(!cfg.isSupported()){ String msg = ManagedMakeMessages.getFormattedString(WARNING_UNSUPPORTED_CONFIGURATION,new String[] {cfg.getName(),cfg.getToolChain().getName()}); buf.append(msg).append(NEWLINE); @@ -1253,31 +1251,31 @@ public class GeneratedMakefileBuilder extends ACBuilder { } consoleOutStream.write(buf.toString().getBytes()); consoleOutStream.flush(); - + if(isParallel || builder.getNumCommands() > 0) { // Remove all markers for this project removeAllMarkers(currentProject); - + // Hook up an error parser manager - String[] errorParsers = cfg.getErrorParserList(); + String[] errorParsers = cfg.getErrorParserList(); ErrorParserManager epm = new ErrorParserManager(getProject(), des.getDefaultBuildDirLocationURI(), this, errorParsers); epm.setOutputStream(consoleOutStream); // This variable is necessary to ensure that the EPM stream stay open // until we explicitly close it. See bug#123302. epmOutputStream = epm.getOutputStream(); - + int status = 0; - + long t1 = System.currentTimeMillis(); if (isParallel) status = ParallelBuilder.build(des, null, null, epmOutputStream, epmOutputStream, monitor, resumeOnErr, buildIncrementaly); else status = builder.build(epmOutputStream, epmOutputStream, monitor); long t2 = System.currentTimeMillis(); - - // Report either the success or failure of our mission + + // Report either the success or failure of our mission buf = new StringBuffer(); - + switch(status){ case IBuildModelBuilder.STATUS_OK: buf.append(ManagedMakeMessages @@ -1289,7 +1287,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { .getResourceString(BUILD_CANCELLED)); break; case IBuildModelBuilder.STATUS_ERROR_BUILD: - String msg = resumeOnErr ? + String msg = resumeOnErr ? ManagedMakeMessages.getResourceString(BUILD_FINISHED_WITH_ERRS) : ManagedMakeMessages.getResourceString(BUILD_STOPPED_ERR); buf.append(msg); @@ -1301,7 +1299,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { break; } buf.append(NEWLINE); - + // Report time and number of threads used // buf.append("Time consumed: "); // buf.append(t2 - t1); @@ -1311,7 +1309,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { // buf.append(ParallelBuilder.lastThreadsUsed); // } // buf.append("\n"); - + // Report time and number of threads used buf.append(ManagedMakeMessages.getFormattedString("CommonBuilder.6", Integer.toString((int)(t2 - t1)))); //$NON-NLS-1$ // buf.append(t2 - t1); @@ -1322,12 +1320,12 @@ public class GeneratedMakefileBuilder extends ACBuilder { } buf.append(NEWLINE); - // Write message on the console + // Write message on the console consoleOutStream.write(buf.toString().getBytes()); consoleOutStream.flush(); epmOutputStream.close(); epmOutputStream = null; - // Generate any error markers that the build has discovered + // Generate any error markers that the build has discovered monitor.subTask(ManagedMakeMessages.getResourceString(MARKERS)); addBuilderMarkers(epm); } else { @@ -1356,7 +1354,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { try { epmOutputStream.close(); } catch (IOException e) { - } + } } if(consoleOutStream != null){ try { @@ -1368,56 +1366,56 @@ public class GeneratedMakefileBuilder extends ACBuilder { monitor.done(); } } - + /** * Called to invoke the MBS Internal Builder for building the given resources in * the given configuration - * + * * This method is considered experimental. Clients implementing this API should expect * possible changes in the API. - * + * * @param resourcesToBuild resources to be built * @param cfg configuration to be built * @param buildIncrementaly if true, incremental build will be performed, * only files that need rebuild will be built. * If false, full rebuild will be performed * @param resumeOnErr if true, build will continue in case of error while building. - * If false the build will stop on the first error + * If false the build will stop on the first error * @param monitor Progress monitor. For every resource built this monitor will consume one unit of work. */ - public void invokeInternalBuilder(IResource[] resourcesToBuild, IConfiguration cfg, + public void invokeInternalBuilder(IResource[] resourcesToBuild, IConfiguration cfg, boolean buildIncrementaly, boolean resumeOnErr, boolean initNewConsole, boolean printFinishedMessage, IProgressMonitor monitor) { - + OutputStream epmOutputStream = null; // Get the project and make sure there's a monitor to cancel the build IProject currentProject = cfg.getOwner().getProject(); if (monitor == null) { monitor = new NullProgressMonitor(); } - + try { int flags = 0; IResourceDelta delta = null; - + if(buildIncrementaly){ flags = BuildDescriptionManager.REBUILD | BuildDescriptionManager.REMOVED | BuildDescriptionManager.DEPS; delta = getDelta(currentProject); } - - + + String[] msgs = new String[2]; msgs[0] = ManagedMakeMessages.getResourceString(INTERNAL_BUILDER); msgs[1] = currentProject.getName(); if(initNewConsole) initNewBuildConsole(currentProject); - + StringBuffer buf = new StringBuffer(); - + if (initNewConsole) { String msg; if (buildIncrementaly) { @@ -1431,7 +1429,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { buf.append(ManagedMakeMessages.getResourceString(INTERNAL_BUILDER_HEADER_NOTE)).append(NEWLINE); } - + if(!cfg.isSupported()){ String msg = ManagedMakeMessages.getFormattedString(WARNING_UNSUPPORTED_CONFIGURATION,new String[] {cfg.getName(),cfg.getToolChain().getName()}); buf.append(msg).append(NEWLINE); @@ -1439,28 +1437,28 @@ public class GeneratedMakefileBuilder extends ACBuilder { } consoleOutStream.write(buf.toString().getBytes()); consoleOutStream.flush(); - + // Remove all markers for this project // TODO remove only necessary markers removeAllMarkers(currentProject); - + IBuildDescription des = BuildDescriptionManager.createBuildDescription(cfg, delta, flags); - + // Hook up an error parser manager - String[] errorParsers = cfg.getErrorParserList(); + String[] errorParsers = cfg.getErrorParserList(); ErrorParserManager epm = new ErrorParserManager(currentProject, des.getDefaultBuildDirLocationURI(), this, errorParsers); epm.setOutputStream(consoleOutStream); // This variable is necessary to ensure that the EPM stream stay open // until we explicitly close it. See bug#123302. epmOutputStream = epm.getOutputStream(); - + boolean errorsFound = false; - + doneBuild: for (int k = 0; k < resourcesToBuild.length; k++) { IBuildResource buildResource = des .getBuildResource(resourcesToBuild[k]); -// step collector +// step collector Set dependentSteps = new HashSet(); // get dependent IO types @@ -1474,36 +1472,36 @@ public class GeneratedMakefileBuilder extends ACBuilder { } monitor.subTask(ManagedMakeMessages.getResourceString("GeneratedMakefileBuilder.buildingFile") + resourcesToBuild[k].getProjectRelativePath()); //$NON-NLS-1$ - + // iterate through all build steps Iterator stepIter = dependentSteps.iterator(); - + while(stepIter.hasNext()) { IBuildStep step = stepIter.next(); - + StepBuilder stepBuilder = new StepBuilder(step, null); - + int status = stepBuilder.build(epmOutputStream, epmOutputStream, new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK)); - - // Refresh the output resource without allowing the user to cancel. - // This is probably unkind, but short of this there is no way to ensure - // the UI is up-to-date with the build results + + // Refresh the output resource without allowing the user to cancel. + // This is probably unkind, but short of this there is no way to ensure + // the UI is up-to-date with the build results IBuildIOType[] outputIOTypes = step.getOutputIOTypes(); - + for(int j = 0; j < outputIOTypes.length; j++ ) { IBuildResource[] resources = outputIOTypes[j].getResources(); - + for(int i = 0; i < resources.length; i++) { IFile file = currentProject.getFile(resources[i].getLocation()); file.refreshLocal(IResource.DEPTH_INFINITE, null); } } - + // check status - + switch (status) { case IBuildModelBuilder.STATUS_OK: // don't print anything if the step was successful, @@ -1529,7 +1527,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { } } - + } // check status @@ -1537,7 +1535,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { buf = new StringBuffer(); buf.append(NEWLINE); - + if (printFinishedMessage) { if (errorsFound) { buf.append(ManagedMakeMessages.getResourceString(BUILD_FAILED_ERR)); @@ -1545,12 +1543,12 @@ public class GeneratedMakefileBuilder extends ACBuilder { buf.append(ManagedMakeMessages.getResourceString("GeneratedMakefileBuilder.buildResourcesFinished")); //$NON-NLS-1$ } } - - // Write message on the console + + // Write message on the console consoleOutStream.write(buf.toString().getBytes()); consoleOutStream.flush(); - // Generate any error markers that the build has discovered + // Generate any error markers that the build has discovered addBuilderMarkers(epm); } catch (Exception e) { if(consoleOutStream != null){ @@ -1571,7 +1569,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { try { epmOutputStream.close(); } catch (IOException e) { - } + } } if(consoleOutStream != null){ try { @@ -1580,10 +1578,10 @@ public class GeneratedMakefileBuilder extends ACBuilder { } } getGenerationProblems().clear(); - monitor.done(); + monitor.done(); } } - + private void removeAllMarkers(IFile file) { IMarker[] markers; try { @@ -1604,7 +1602,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { } } } - + public void cleanFile(IFile file, IProgressMonitor monitor) { monitor.subTask(ManagedMakeMessages.getResourceString("GeneratedMakefileBuilder.0") //$NON-NLS-1$ @@ -1632,14 +1630,14 @@ public class GeneratedMakefileBuilder extends ACBuilder { int flags = BuildDescriptionManager.REBUILD | BuildDescriptionManager.REMOVED; IResourceDelta delta = getDelta(currentProject); - + try { IBuildDescription des = BuildDescriptionManager .createBuildDescription(cfg, delta, flags); IBuildResource buildResource = des.getBuildResource(file); - + if (buildResource != null) { // step collector @@ -1685,7 +1683,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { // TODO Auto-generated catch block e.printStackTrace(); } - + } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java index 5478f2e0efa..e23dbd5d9f2 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java @@ -1,16 +1,17 @@ /******************************************************************************* - * Copyright (c) 2003, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html + * Copyright (c) 2003, 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 + * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: - * IBM Rational Software - Initial API and implementation - * ARM Ltd. - Minor changes to echo commands - * IBM Corporation - * Anna Dushistova (Mentor Graphics) - [307244] extend visibility of fields in GnuMakefileGenerator - * James Blackburn (Broadcom Corp.) + * Contributors: + * IBM Rational Software - Initial API and implementation + * ARM Ltd. - Minor changes to echo commands + * IBM Corporation + * Anna Dushistova (Mentor Graphics) - [307244] extend visibility of fields in GnuMakefileGenerator + * James Blackburn (Broadcom Corp.) + * Marc-Andre Laperle *******************************************************************************/ package org.eclipse.cdt.managedbuilder.makegen.gnu; @@ -41,7 +42,6 @@ import org.eclipse.cdt.core.settings.model.ICSourceEntry; import org.eclipse.cdt.core.settings.model.util.CDataUtil; import org.eclipse.cdt.core.settings.model.util.IPathSettingsContainerVisitor; import org.eclipse.cdt.core.settings.model.util.PathSettingsContainer; -import org.eclipse.cdt.internal.core.model.Util; import org.eclipse.cdt.managedbuilder.core.BuildException; import org.eclipse.cdt.managedbuilder.core.IBuildObject; import org.eclipse.cdt.managedbuilder.core.IBuilder; @@ -812,6 +812,30 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 { return false; } + + private static void save(StringBuffer buffer, IFile file) throws CoreException { + String encoding = null; + try { + encoding = file.getCharset(); + } catch (CoreException ce) { + // use no encoding + } + + byte[] bytes = null; + if (encoding != null) { + try { + bytes = buffer.toString().getBytes(encoding); + } catch (Exception e) { + } + } else { + bytes = buffer.toString().getBytes(); + } + + ByteArrayInputStream stream = new ByteArrayInputStream(bytes); + // use a platform operation to update the resource contents + boolean force = true; + file.setContents(stream, force, false, null); // Don't record history + } /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#regenerateDependencies() @@ -993,7 +1017,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 { makeBuf.append(addSources(module)); // Save the files - Util.save(makeBuf, modMakefile); + save(makeBuf, modMakefile); } /** @@ -1053,7 +1077,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 { } // For now, just save the buffer that was populated when the rules were created - Util.save(macroBuffer, fileHandle); + save(macroBuffer, fileHandle); } @@ -1139,7 +1163,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 { buffer.append(NEWLINE + addSubdirectories()); // Save the file - Util.save(buffer, fileHandle); + save(buffer, fileHandle); } /** @@ -1170,7 +1194,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 { buffer.append(targetRules); // Save the file - Util.save(buffer, fileHandle); + save(buffer, fileHandle); } @@ -2379,7 +2403,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 { // Figure out the output paths String optDotExt = EMPTY_STRING; - if (outputExtension != null && outputExtension.length() > 0) + if (outputExtension.length() > 0) optDotExt = DOT + outputExtension; Vector ruleOutputs = new Vector(); @@ -3570,7 +3594,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 { if (bufferLine.endsWith(":")) { //$NON-NLS-1$ StringBuffer outBuffer = addDefaultHeader(); outBuffer.append(inBuffer); - Util.save(outBuffer, makefile); + save(outBuffer, makefile); return true; } } @@ -3709,7 +3733,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 { // Write them out to the makefile if (save) { - Util.save(outBuffer, makefile); + save(outBuffer, makefile); return true; } return false; @@ -4280,7 +4304,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 { // Make sure the folder is marked as derived so it is not added to CM if (!folder.isDerived()) { - folder.setDerived(true); + folder.setDerived(true, null); } } @@ -4306,7 +4330,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 { newFile.create(contents, false, new SubProgressMonitor(monitor, 1)); // Make sure the new file is marked as derived if (!newFile.isDerived()) { - newFile.setDerived(true); + newFile.setDerived(true, null); } } diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/RefreshPolicyTab.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/RefreshPolicyTab.java index ab743994fdd..569bb5ed68a 100644 --- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/RefreshPolicyTab.java +++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/properties/RefreshPolicyTab.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 IBM Corporation and others. + * Copyright (c) 2011, 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 @@ -25,7 +25,6 @@ import org.eclipse.cdt.core.resources.RefreshScopeManager; import org.eclipse.cdt.core.settings.model.ICResourceDescription; import org.eclipse.cdt.managedbuilder.internal.ui.Messages; import org.eclipse.cdt.ui.CDTSharedImages; -import org.eclipse.cdt.ui.newui.AbstractCPropertyTab; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; @@ -67,7 +66,7 @@ import org.eclipse.ui.model.WorkbenchLabelProvider; * @since 8.0 */ @SuppressWarnings("restriction") -public class RefreshPolicyTab extends AbstractCPropertyTab { +public class RefreshPolicyTab extends AbstractCBuildPropertyTab { private final Image IMG_FOLDER = CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_FOLDER); private final Image IMG_FILE = ManagedBuilderUIImages.get(ManagedBuilderUIImages.IMG_FILE_OBJ); @@ -83,45 +82,82 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { private TreeViewer fTree; private RefreshScopeManager fManager; private IProject fProject; - - private ArrayList<_Entry> fSrc; - private List fResourcesToRefresh; - private HashMap> fResourceToExclusionsMap = new HashMap>(); - + private HashMap>> fConfigurationToResourcesToExclusionsMap; public RefreshPolicyTab() { fManager = RefreshScopeManager.getInstance(); } - private void loadInfo() { - fResourcesToRefresh = new LinkedList(fManager.getResourcesToRefresh(fProject)); - if (fResourcesToRefresh != null) { - Iterator iterator = fResourcesToRefresh.iterator(); - while (iterator.hasNext()) { - IResource resource = iterator.next(); - fResourceToExclusionsMap.put(resource, new LinkedList(fManager.getExclusions(resource))); - } - } + private HashMap> getResourcesToExclusionsMap(String configName) { + HashMap> resourceMap = fConfigurationToResourcesToExclusionsMap.get(configName); + if (resourceMap == null) { + resourceMap = new HashMap>(); + fConfigurationToResourcesToExclusionsMap.put(configName, resourceMap); + } + + return resourceMap; } - private List getExclusions(IResource resource) { - List exclusions = fResourceToExclusionsMap.get(resource); + private String getConfigName() { + return this.getCfg().getName(); + } + + private HashMap>> copyHashMap(HashMap>> source) { + + HashMap>> target = new HashMap>>(); + Iterator config_iterator = source.keySet().iterator(); + // for each Configuration ... + while (config_iterator.hasNext()) { + String configName = config_iterator.next(); + + HashMap> source_resourceMap = source.get(configName); + HashMap> target_resourceMap = new HashMap>(); + + Iterator resource_iterator = source_resourceMap.keySet().iterator(); + while (resource_iterator.hasNext()) { + IResource source_resource = resource_iterator.next(); + List source_exclusions = source_resourceMap.get(source_resource); + List target_exclusions = new LinkedList(); + for (RefreshExclusion exclusion : source_exclusions) { + // ADD each exclusion to the target exclusion list. + RefreshExclusion target_exclusion = (RefreshExclusion) exclusion.clone(); + target_exclusions.add(target_exclusion); + } + + // ADD the exclusion list for this resource + target_resourceMap.put(source_resource, target_exclusions); + } + + // ADD each resource. + target.put(configName, target_resourceMap); + } + return target; + } + + private void loadInfo() { + HashMap>> configMap = fManager.getConfigurationToResourcesMap(fProject); + fConfigurationToResourcesToExclusionsMap = copyHashMap(configMap); + } + + private List getExclusions(String configName, IResource resource) { + HashMap> resourceMap = getResourcesToExclusionsMap(configName); + List exclusions = resourceMap.get(resource); if(exclusions == null) { exclusions = new LinkedList(); - fResourceToExclusionsMap.put(resource, exclusions); + resourceMap.put(resource, exclusions); } - return fResourceToExclusionsMap.get(resource); + return resourceMap.get(resource); } /** * Wrapper for IResource/RefreshExclusion */ class _Entry { - //if this is not a resource to refresh, resourceToRefresh will be null + //if this is a refresh exclusion, resourceToRefresh will be null IResource resourceToRefresh = null; - //if this is not a refresh exclusion, exclusion will be null + //if this is a resource to refresh, exclusion will be null RefreshExclusion exclusion = null; //if this is a refresh exclusion, parent is the Exceptions node this is a child of @@ -135,7 +171,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { _Entry(IResource _ent) { resourceToRefresh = _ent; - if (getExclusions(resourceToRefresh) != null && getExclusions(resourceToRefresh).size() > 0) + if (getExclusions(getConfigName(),resourceToRefresh) != null && getExclusions(getConfigName(),resourceToRefresh).size() > 0) exceptions_node = new _Exception_Node(this); } @@ -206,7 +242,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { if (parentEntry.isExclusion()) { parentEntry.exclusion.removeNestedExclusion(exclusionToRemove); } else { - List exceptions = getExclusions(parentEntry.resourceToRefresh); + List exceptions = getExclusions(getConfigName(), parentEntry.resourceToRefresh); exceptions.remove(exclusionToRemove); } @@ -217,8 +253,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { parentEntry.exceptions_node = null; } } else { //this is a resource to refresh - fResourceToExclusionsMap.remove(resourceToRefresh); - fResourcesToRefresh.remove(resourceToRefresh); + getResourcesToExclusionsMap(getConfigName()).remove(resourceToRefresh); fSrc.remove(this); } } @@ -239,8 +274,8 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { if (parent.exclusion.getNestedExclusions() != null) iterator = parent.exclusion.getNestedExclusions().iterator(); } else { - if (getExclusions(parent.resourceToRefresh) != null) - iterator = getExclusions(parent.resourceToRefresh).iterator(); + if (getExclusions(getConfigName(),parent.resourceToRefresh) != null) + iterator = getExclusions(getConfigName(),parent.resourceToRefresh).iterator(); } if (iterator != null) { @@ -256,10 +291,10 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { if (parent.isExclusion()) { parent.exclusion.addNestedExclusion(exclusion); } else { - List exclusions = getExclusions(parent.resourceToRefresh); + List exclusions = getExclusions(getConfigName(),parent.resourceToRefresh); if (exclusions == null) { exclusions = new LinkedList(); - fResourceToExclusionsMap.put(parent.resourceToRefresh, exclusions); + getResourcesToExclusionsMap(getConfigName()).put(parent.resourceToRefresh, exclusions); } exclusions.add(exclusion); } @@ -309,8 +344,6 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { } } - - /* (non-Javadoc) * @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#createControls(org.eclipse.swt.widgets.Composite) */ @@ -332,7 +365,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { Group g1 = setupGroup(usercomp, Messages.RefreshPolicyTab_resourcesGroupLabel, 2, GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL); fSrc = new ArrayList<_Entry>(); - generateTreeContent(fProject); + generateTreeContent(); fTree = new TreeViewer(g1); fTree.getTree().setLayoutData(new GridData(GridData.FILL_BOTH)); @@ -446,14 +479,19 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { } } - private void generateTreeContent(IProject project) { - Iterator iterator = fResourcesToRefresh.iterator(); + private void generateTreeContent() { + Iterator iterator = getResourcesToExclusionsMap(getConfigName()).keySet().iterator(); while (iterator.hasNext()) { _Entry top = new _Entry(iterator.next()); fSrc.add(top); } } + private void clearTreeContent() { + // Just clear the fSrc. + fSrc.clear(); + } + @Override protected void performApply(ICResourceDescription src, ICResourceDescription dst) { performOK(); @@ -462,13 +500,20 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { @Override protected void performDefaults() { // TODO Auto-generated method stub - } @Override protected void updateData(ICResourceDescription cfg) { - // TODO Auto-generated method stub - + // only expand on first update. + if (page.isMultiCfg()) { + setAllVisible(false, null); + return; + } else { + clearTreeContent(); + generateTreeContent(); + fTree.refresh(); + fTree.expandAll(); + } } @Override @@ -488,7 +533,8 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { @Override public Object[] getChildren(Object element) { ArrayList filteredChildren = new ArrayList(Arrays.asList(super.getChildren(element))); - Iterator iterator = fResourcesToRefresh.iterator(); + Iterator iterator = getResourcesToExclusionsMap(getConfigName()).keySet().iterator(); //fResourcesToRefresh.iterator(); + while (iterator.hasNext()) { filteredChildren.remove(iterator.next()); } @@ -508,7 +554,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { switch (x) { case IDX_ADD_RESOURCE: //TODO: Phase one implementation - folders only - need to change this for Phase two - fResourcesToRefresh.size(); + CheckedTreeSelectionDialog addResourceDialog = new CheckedTreeSelectionDialog(shell, new WorkbenchLabelProvider(), new FilteredContainerContentProvider()); addResourceDialog.setInput(ResourcesPlugin.getWorkspace()); @@ -520,7 +566,8 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { IResource resource = (IResource) result[i]; _Entry newResource = new _Entry(resource); //update the model element in this tab - fResourcesToRefresh.add(resource); + getResourcesToExclusionsMap(getConfigName()).put(resource,new LinkedList()); + //update tree fSrc.add(newResource); } @@ -537,7 +584,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { if (sel.isExclusion()) { addExceptionDialog = new RefreshPolicyExceptionDialog(shell, sel.exclusion, true); } else { - addExceptionDialog = new RefreshPolicyExceptionDialog(shell, sel.resourceToRefresh, getExclusions(sel.resourceToRefresh), true); + addExceptionDialog = new RefreshPolicyExceptionDialog(shell, sel.resourceToRefresh, getExclusions(getConfigName(),sel.resourceToRefresh), true); } if (addExceptionDialog.open() == Window.OK) { RefreshExclusion newExclusion = addExceptionDialog.getResult(); @@ -624,15 +671,13 @@ public class RefreshPolicyTab extends AbstractCPropertyTab { */ @Override protected void performOK() { - fManager.setResourcesToRefresh(fProject, fResourcesToRefresh); - Iterator iterator = fResourcesToRefresh.iterator(); - while (iterator.hasNext()) { - IResource resource = iterator.next(); - fManager.clearExclusions(resource); - List exclusions = fResourceToExclusionsMap.get(resource); - fManager.setExclusions(resource, exclusions); + Iterator config_iterator = fConfigurationToResourcesToExclusionsMap.keySet().iterator(); + + while (config_iterator.hasNext()) { + String configName = config_iterator.next(); + + fManager.setResourcesToExclusionsMap(fProject, configName, getResourcesToExclusionsMap(configName)); } - try { fManager.persistSettings(getResDesc().getConfiguration().getProjectDescription()); } catch (CoreException e) { diff --git a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/resources/tests/RefreshScopeTests.java b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/resources/tests/RefreshScopeTests.java index 7a6384022c1..81c4628ec69 100644 --- a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/resources/tests/RefreshScopeTests.java +++ b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/resources/tests/RefreshScopeTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 IBM Corporation and others. + * Copyright (c) 2011, 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 @@ package org.eclipse.cdt.core.resources.tests; import java.io.File; import java.io.IOException; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -54,6 +55,7 @@ public class RefreshScopeTests extends TestCase { private IFolder fFolder4; private IFolder fFolder5; private IFolder fFolder6; + private String config1,config2; /* (non-Javadoc) * @see junit.framework.TestCase#setUp() @@ -74,6 +76,9 @@ public class RefreshScopeTests extends TestCase { IWorkspaceRoot root = CTestPlugin.getWorkspace().getRoot(); IProject project = root.getProject("testRefreshScope"); + config1 = "Debug"; + config2 = "Release"; + // create some folders // structure is: /* @@ -123,56 +128,92 @@ public class RefreshScopeTests extends TestCase { } public void testAddDeleteResource() throws CoreException { - RefreshScopeManager manager = RefreshScopeManager.getInstance(); manager.clearAllData(); - manager.addResourceToRefresh(fProject, fFolder1); + // TEST 1: + // add resource "folder1" under config1. + manager.addResourceToRefresh(fProject, config1, fFolder1); + // now, check that it was added. + List config1_resources = manager.getResourcesToRefresh(fProject, config1); + assertEquals(config1_resources.size(), 2); + assertEquals(config1_resources.contains(fProject), true); + assertEquals(config1_resources.contains(fFolder1), true); - IResource[] resources = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]); - assertEquals(resources.length, 1); - assertEquals(fFolder1, resources[0]); + // TEST 2: + // add resource "folder2" under config1 + manager.addResourceToRefresh(fProject, config1, fFolder2); + // now check to see that it and "folder1" are still there. + config1_resources = manager.getResourcesToRefresh(fProject, config1); + assertEquals(config1_resources.size(), 3); // 3 because by default the project is always there. + assertEquals(config1_resources.contains(fProject), true); + assertEquals(config1_resources.contains(fFolder1), true); + assertEquals(config1_resources.contains(fFolder2), true); - manager.addResourceToRefresh(fProject, fFolder2); - resources = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]); - assertEquals(resources.length, 2); - assertEquals(fFolder1, resources[0]); - assertEquals(fFolder2, resources[1]); + // make sure it wasn't added under "Release", which should be empty now, excpet for the default project resource. + List config2_resources = manager.getResourcesToRefresh(fProject, config2); + assertEquals(config2_resources.size(),1); + assertEquals(config2_resources.contains(fProject), true); - // first try deleting a resource that was never added... the project - manager.deleteResourceToRefresh(fProject, fProject); - IResource[] resourcesAfterDelete = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]); - assertEquals(resourcesAfterDelete.length, 2); - assertEquals(fFolder1, resources[0]); - assertEquals(fFolder2, resources[1]); + // and add one under config 2. + manager.addResourceToRefresh(fProject, config2, fFolder1); + config2_resources = manager.getResourcesToRefresh(fProject, config2); + assertEquals(config2_resources.size(),2); + assertEquals(config2_resources.contains(fProject), true); + assertEquals(config2_resources.contains(fFolder1), true); + // TEST 3: + // first try deleting a resource that was never added... folder5 + manager.deleteResourceToRefresh(fProject, config1, fFolder5); + List config1_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config1); + assertEquals(config1_resourcesAfterDelete.size(), 3); + assertEquals(config1_resources.contains(fProject), true); + assertEquals(config1_resources.contains(fFolder1), true); + assertEquals( config1_resources.contains(fFolder2), true); + // ditto for config2, but this time we did add the resource, to make sure fFolder1 wasn't added. + manager.deleteResourceToRefresh(fProject, config2, fFolder5); + List config2_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config2); + assertEquals(config2_resourcesAfterDelete.size(), 2); + assertEquals(config2_resources.contains(fProject), true); + assertEquals(config2_resources.contains(fFolder1), true); + + + // TEST 4: // now delete the resources from the manager one by one - manager.deleteResourceToRefresh(fProject, resources[1]); - resourcesAfterDelete = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]); - assertEquals(resourcesAfterDelete.length, 1); - assertEquals(resourcesAfterDelete[0], resources[0]); + manager.deleteResourceToRefresh(fProject, config1, config1_resources.get(config1_resources.indexOf(fFolder2))); + config1_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config1); + assertEquals(config1_resourcesAfterDelete.size(), 2); + assertEquals(config1_resourcesAfterDelete.contains(fProject), true); + assertEquals(config1_resourcesAfterDelete.contains(fFolder1), true); - manager.deleteResourceToRefresh(fProject, resources[0]); - resourcesAfterDelete = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]); - assertEquals(resourcesAfterDelete.length, 0); + manager.deleteResourceToRefresh(fProject, config1, config1_resources.get(config1_resources.indexOf(fFolder1))); + config1_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config1); + assertEquals(config1_resourcesAfterDelete.size(), 1); + assertEquals(config1_resourcesAfterDelete.contains(fProject), true); + // and ditto for config2 + manager.deleteResourceToRefresh(fProject, config2, config2_resources.get(config2_resources.indexOf(fFolder1))); + config2_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config2); + assertEquals(config2_resourcesAfterDelete.size(), 1); + assertEquals(config2_resourcesAfterDelete.contains(fProject), true); } - public void testSetResourcesToRefresh() { + + public void testSetResourcesToExclusionsMapRefresh() { RefreshScopeManager manager = RefreshScopeManager.getInstance(); manager.clearAllData(); - List resources = new LinkedList(); - resources.add(fFolder1); - resources.add(fFolder2); - manager.setResourcesToRefresh(fProject, resources); + HashMap> config1_resourceMap = new HashMap>(); + config1_resourceMap.put(fFolder1,new LinkedList()); + config1_resourceMap.put(fFolder2,new LinkedList()); + manager.setResourcesToExclusionsMap(fProject, config1, config1_resourceMap); - IResource[] resourcesAfterSet = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]); - assertEquals(resourcesAfterSet.length, 2); - assertEquals(fFolder1, resourcesAfterSet[0]); - assertEquals(fFolder2, resourcesAfterSet[1]); + List config1_resourcesAfterSet = manager.getResourcesToRefresh(fProject, config1); + assertEquals(config1_resourcesAfterSet.size(), 2); + assertEquals(config1_resourcesAfterSet.contains(fFolder1), true); + assertEquals(config1_resourcesAfterSet.contains(fFolder2), true); manager.clearResourcesToRefresh(fProject); @@ -182,28 +223,31 @@ public class RefreshScopeTests extends TestCase { RefreshScopeManager manager = RefreshScopeManager.getInstance(); manager.clearAllData(); - manager.addResourceToRefresh(fProject, fProject); - RefreshExclusion exclusion1 = new TestExclusion(); - manager.addExclusion(fProject, exclusion1); - RefreshExclusion exclusion2 = new TestExclusion(); - manager.addExclusion(fProject, exclusion2); + IResource config1_resource = fProject; + + + manager.addResourceToRefresh(fProject, config1, config1_resource); + RefreshExclusion config1_exclusion1 = new TestExclusion(); + manager.addExclusion(fProject, config1, config1_resource, config1_exclusion1); + RefreshExclusion config1_exclusion2 = new TestExclusion(); + manager.addExclusion(fProject, config1, config1_resource, config1_exclusion2); // make sure the exclusions are there - List exclusionsList = manager.getExclusions(fProject); + List exclusionsList = manager.getExclusions(fProject, config1, config1_resource); RefreshExclusion[] exclusionsArray = exclusionsList.toArray(new RefreshExclusion[0]); assertEquals(exclusionsArray.length, 2); - assertEquals(exclusionsArray[0], exclusion1); - assertEquals(exclusionsArray[1], exclusion2); + assertEquals(exclusionsArray[0], config1_exclusion1); + assertEquals(exclusionsArray[1], config1_exclusion2); // remove the exclusions one by one - manager.removeExclusion(fProject, exclusion2); - exclusionsList = manager.getExclusions(fProject); + manager.removeExclusion(fProject, config1, config1_resource, config1_exclusion2); + exclusionsList = manager.getExclusions(fProject,config1,config1_resource); exclusionsArray = exclusionsList.toArray(new RefreshExclusion[0]); assertEquals(exclusionsArray.length, 1); - assertEquals(exclusionsArray[0], exclusion1); + assertEquals(exclusionsArray[0], config1_exclusion1); - manager.removeExclusion(fProject, exclusion1); - exclusionsList = manager.getExclusions(fProject); + manager.removeExclusion(fProject, config1, config1_resource, config1_exclusion1); + exclusionsList = manager.getExclusions(fProject, config1,config1_resource); exclusionsArray = exclusionsList.toArray(new RefreshExclusion[0]); assertEquals(exclusionsArray.length, 0); @@ -213,24 +257,46 @@ public class RefreshScopeTests extends TestCase { RefreshScopeManager manager = RefreshScopeManager.getInstance(); manager.clearAllData(); - manager.addResourceToRefresh(fProject, fProject); + IResource config1_resource = fProject; + IResource config2_resource = fFolder1; - RefreshExclusion exclusion1 = new TestExclusion(); - manager.addExclusion(fProject, exclusion1); - RefreshExclusion exclusion2 = new TestExclusion(); - manager.addExclusion(fProject, exclusion2); + //add a resource and two exclusions for config1. + manager.addResourceToRefresh(fProject, config1, config1_resource); + RefreshExclusion config1_exclusion1 = new TestExclusion(); + manager.addExclusion(fProject, config1, config1_resource, config1_exclusion1); + RefreshExclusion config1_exclusion2 = new TestExclusion(); + manager.addExclusion(fProject, config1, config1_resource, config1_exclusion2); // add a nested exclusion to the first exclusion - RefreshExclusion exclusion3 = new TestExclusion(); - exclusion1.addNestedExclusion(exclusion3); + RefreshExclusion config1_exclusion3 = new TestExclusion(); + config1_exclusion1.addNestedExclusion(config1_exclusion3); // add an instance to the second exclusion - ExclusionInstance instance = new ExclusionInstance(); - instance.setDisplayString("foo"); - instance.setResource(fFolder2); - instance.setExclusionType(ExclusionType.RESOURCE); - instance.setParentExclusion(exclusion2); - exclusion2.addExclusionInstance(instance); + ExclusionInstance config1_instance = new ExclusionInstance(); + config1_instance.setDisplayString("foo"); + config1_instance.setResource(fFolder2); + config1_instance.setExclusionType(ExclusionType.RESOURCE); + config1_instance.setParentExclusion(config1_exclusion2); + config1_exclusion2.addExclusionInstance(config1_instance); + + //add a resource and two exclusions for config2. + manager.addResourceToRefresh(fProject, config2, config2_resource); + RefreshExclusion config2_exclusion1 = new TestExclusion(); + manager.addExclusion(fProject, config2, config2_resource, config2_exclusion1); + RefreshExclusion config2_exclusion2 = new TestExclusion(); + manager.addExclusion(fProject, config2, config2_resource, config2_exclusion2); + + // add a nested exclusion to the first exclusion + RefreshExclusion config2_exclusion3 = new TestExclusion(); + config2_exclusion1.addNestedExclusion(config2_exclusion3); + + // add an instance to the second exclusion + ExclusionInstance config2_instance = new ExclusionInstance(); + config2_instance.setDisplayString("foo"); + config2_instance.setResource(fFolder2); + config2_instance.setExclusionType(ExclusionType.RESOURCE); + config2_instance.setParentExclusion(config2_exclusion2); + config2_exclusion2.addExclusionInstance(config1_instance); ICProjectDescription projectDescription = CCorePlugin.getDefault().getProjectDescription(fProject, true); @@ -251,53 +317,96 @@ public class RefreshScopeTests extends TestCase { fail(); } - // make sure we got the same stuff we saved + // make sure we got the same stuff we saved for config1 // the project should be set to refresh its root - List resources = manager.getResourcesToRefresh(fProject); - assertEquals(resources.size(), 1); - assertEquals(resources.toArray(new IResource[0])[0], fProject); + List config1_resources = manager.getResourcesToRefresh(fProject,config1); + assertEquals(config1_resources.size(), 1); + assertEquals(config1_resources.toArray(new IResource[0])[0], config1_resource); // there should be 2 top-level exclusions - List exclusions = manager.getExclusions(fProject); - assertEquals(2, exclusions.size()); - RefreshExclusion[] exclusionsArray = exclusions.toArray(new RefreshExclusion[0]); + List config1_exclusions = manager.getExclusions(fProject, config1,config1_resource); + assertEquals(2, config1_exclusions.size()); + RefreshExclusion[] config1_exclusionsArray = config1_exclusions.toArray(new RefreshExclusion[0]); // both exclusions should have parent resource set to the project - assertEquals(fProject, exclusionsArray[0].getParentResource()); - assertEquals(fProject, exclusionsArray[1].getParentResource()); + assertEquals(config1_resource, config1_exclusionsArray[0].getParentResource()); + assertEquals(config1_resource, config1_exclusionsArray[1].getParentResource()); // the first exclusion should have one nested exclusion - List nestedExclusions1 = exclusionsArray[0].getNestedExclusions(); - assertEquals(nestedExclusions1.size(), 1); - RefreshExclusion[] nestedExclusionsArray = nestedExclusions1.toArray(new RefreshExclusion[0]); + List config1_nestedExclusions1 = config1_exclusionsArray[0].getNestedExclusions(); + assertEquals(config1_nestedExclusions1.size(), 1); + RefreshExclusion[] config1_nestedExclusionsArray = config1_nestedExclusions1.toArray(new RefreshExclusion[0]); // the nested exclusion should have its parent exclusion set properly - assertEquals(nestedExclusionsArray[0].getParentExclusion(), exclusionsArray[0]); + assertEquals(config1_nestedExclusionsArray[0].getParentExclusion(), config1_exclusionsArray[0]); // the second exclusion should have no nested exclusions - List nestedExclusions2 = exclusionsArray[1].getNestedExclusions(); - assertEquals(nestedExclusions2.size(), 0); + List config1_nestedExclusions2 = config1_exclusionsArray[1].getNestedExclusions(); + assertEquals(config1_nestedExclusions2.size(), 0); // the second exclusion should have an instance - List instances = exclusionsArray[1].getExclusionInstances(); - assertEquals(1, instances.size()); - ExclusionInstance[] instancesArray = instances.toArray(new ExclusionInstance[0]); - ExclusionInstance loadedInstance = instancesArray[0]; + List config1_instances = config1_exclusionsArray[1].getExclusionInstances(); + assertEquals(1, config1_instances.size()); + ExclusionInstance[] config1_instancesArray = config1_instances.toArray(new ExclusionInstance[0]); + ExclusionInstance config1_loadedInstance = config1_instancesArray[0]; // check the contents of the instance - assertEquals("foo", loadedInstance.getDisplayString()); - assertEquals(fFolder2, loadedInstance.getResource()); - assertEquals(ExclusionType.RESOURCE, loadedInstance.getExclusionType()); + assertEquals("foo", config1_loadedInstance.getDisplayString()); + assertEquals(fFolder2, config1_loadedInstance.getResource()); + assertEquals(ExclusionType.RESOURCE, config1_loadedInstance.getExclusionType()); + + // clear data for config1 + manager.deleteResourceToRefresh(fProject, config1, config1_resource); + + // make sure we got the same stuff we saved for config2 + // the project should be set to refresh its root + List config2_resources = manager.getResourcesToRefresh(fProject,config2); + assertEquals(config2_resources.size(), 2); + assertEquals(config2_resources.contains(config2_resource), true); + + // there should be 2 top-level exclusions + List config2_exclusions = manager.getExclusions(fProject,config2,config2_resource); + assertEquals(2, config2_exclusions.size()); + RefreshExclusion[] config2_exclusionsArray = config2_exclusions.toArray(new RefreshExclusion[0]); + + // both exclusions should have parent resource set to the project + assertEquals(config2_resource, config2_exclusionsArray[0].getParentResource()); + assertEquals(config2_resource, config2_exclusionsArray[1].getParentResource()); + + // the first exclusion should have one nested exclusion + List config2_nestedExclusions1 = config2_exclusionsArray[0].getNestedExclusions(); + assertEquals(config2_nestedExclusions1.size(), 1); + RefreshExclusion[] config2_nestedExclusionsArray = config2_nestedExclusions1.toArray(new RefreshExclusion[0]); + // the nested exclusion should have its parent exclusion set properly + assertEquals(config2_nestedExclusionsArray[0].getParentExclusion(), config2_exclusionsArray[0]); + + // the second exclusion should have no nested exclusions + List config2_nestedExclusions2 = config2_exclusionsArray[1].getNestedExclusions(); + assertEquals(config2_nestedExclusions2.size(), 0); + + // the second exclusion should have an instance + List config2_instances = config2_exclusionsArray[1].getExclusionInstances(); + assertEquals(1, config2_instances.size()); + ExclusionInstance[] config2_instancesArray = config2_instances.toArray(new ExclusionInstance[0]); + ExclusionInstance config2_loadedInstance = config2_instancesArray[0]; + + // check the contents of the instance + assertEquals("foo", config2_loadedInstance.getDisplayString()); + assertEquals(fFolder2, config2_loadedInstance.getResource()); + assertEquals(ExclusionType.RESOURCE, config2_loadedInstance.getExclusionType()); // cleanup manager.clearAllData(); } + public void testResourceExclusion() { RefreshScopeManager manager = RefreshScopeManager.getInstance(); manager.clearAllData(); - manager.addResourceToRefresh(fProject, fProject); + IResource config1_resource = fProject; + + manager.addResourceToRefresh(fProject, config1, config1_resource); // create a series of nested exclusions that include/exclude certain folders // will be included/excluded as follows @@ -319,7 +428,7 @@ public class RefreshScopeTests extends TestCase { ExclusionInstance instance2 = new ExclusionInstance(); instance2.setResource(fFolder2); exclusion1.addExclusionInstance(instance2); - manager.addExclusion(fProject, exclusion1); + manager.addExclusion(fProject, config1, config1_resource, exclusion1); ResourceExclusion exclusion2 = new ResourceExclusion(); ExclusionInstance instance3 = new ExclusionInstance(); @@ -335,13 +444,13 @@ public class RefreshScopeTests extends TestCase { // now check and see if the right folders are included/excluded - assertEquals(true, manager.shouldResourceBeRefreshed(fProject)); - assertEquals(false, manager.shouldResourceBeRefreshed(fFolder1)); - assertEquals(false, manager.shouldResourceBeRefreshed(fFolder2)); - assertEquals(true, manager.shouldResourceBeRefreshed(fFolder3)); - assertEquals(false, manager.shouldResourceBeRefreshed(fFolder4)); - assertEquals(true, manager.shouldResourceBeRefreshed(fFolder5)); - assertEquals(false, manager.shouldResourceBeRefreshed(fFolder6)); + assertEquals(true, manager.shouldResourceBeRefreshed(config1, config1_resource)); + assertEquals(false, manager.shouldResourceBeRefreshed(config1, fFolder1)); + assertEquals(false, manager.shouldResourceBeRefreshed(config1, fFolder2)); + assertEquals(true, manager.shouldResourceBeRefreshed(config1, fFolder3)); + assertEquals(false, manager.shouldResourceBeRefreshed(config1, fFolder4)); + assertEquals(true, manager.shouldResourceBeRefreshed(config1, fFolder5)); + assertEquals(false, manager.shouldResourceBeRefreshed(config1, fFolder6)); // now let's create a bunch of files in these directories using java.io.File (so that we don't get // resource deltas happening), and refresh the project according to the policy. We should only see the files @@ -412,13 +521,12 @@ public class RefreshScopeTests extends TestCase { manager.clearAllData(); // by default, a project should refresh its root - List resourcesToRefresh = manager.getResourcesToRefresh(fProject); + List resourcesToRefresh = manager.getResourcesToRefresh(fProject, config1); assertEquals(1, resourcesToRefresh.size()); - IResource[] resourceArray = resourcesToRefresh.toArray(new IResource[0]); - assertEquals(fProject, resourceArray[0]); + assertEquals(resourcesToRefresh.contains(fProject), true); // there should be no exclusions - List exclusions = manager.getExclusions(fProject); + List exclusions = manager.getExclusions(fProject, config1, fProject); assertEquals(0, exclusions.size()); ICProjectDescription projectDescription = CCorePlugin.getDefault().getProjectDescription(fProject); @@ -440,12 +548,12 @@ public class RefreshScopeTests extends TestCase { // test the defaults again // by default, a project should refresh its root - resourcesToRefresh = manager.getResourcesToRefresh(fProject); + resourcesToRefresh = manager.getResourcesToRefresh(fProject, config1); assertEquals(1, resourcesToRefresh.size()); - resourceArray = resourcesToRefresh.toArray(new IResource[0]); - assertEquals(fProject, resourceArray[0]); + assertEquals(resourcesToRefresh.contains(fProject), true); + // there should be no exclusions - exclusions = manager.getExclusions(fProject); + exclusions = manager.getExclusions(fProject, config1, fProject); assertEquals(0, exclusions.size()); } diff --git a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/resources/tests/TestExclusion.java b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/resources/tests/TestExclusion.java index 79a5ad5c83f..50505af5b51 100644 --- a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/resources/tests/TestExclusion.java +++ b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/resources/tests/TestExclusion.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 IBM Corporation and others. + * Copyright (c) 2011, 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 @@ -31,4 +31,11 @@ public class TestExclusion extends RefreshExclusion { public boolean supportsExclusionInstances() { return false; } + + @Override + public Object clone() { + TestExclusion clone = new TestExclusion(); + copyTo(clone); + return clone; + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMProviderTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMProviderTests.java index 97cc666e0e3..d3fe6fa95c2 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMProviderTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMProviderTests.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Andrew Ferguson (Symbian) - Initial implementation + * Andrew Ferguson (Symbian) - Initial implementation *******************************************************************************/ package org.eclipse.cdt.internal.pdom.tests; @@ -80,13 +80,11 @@ public class PDOMProviderTests extends PDOMTestBase { TestSourceReader.createFile(cproject2.getProject(), new Path("/source.cpp"), "namespace X { class A {}; }\n\n"); CCorePlugin.getIndexManager().joinIndexer(3000, npm()); - IndexProviderManager ipm= CCoreInternals.getPDOMManager().getIndexProviderManager(); ipm.addIndexProvider(new ReadOnlyPDOMProviderBridge( new IReadOnlyPDOMProvider() { @Override - public IPDOMDescriptor[] getDescriptors( - ICConfigurationDescription config) { + public IPDOMDescriptor[] getDescriptors(ICConfigurationDescription config) { return new IPDOMDescriptor[] { new IPDOMDescriptor() { @Override @@ -98,16 +96,14 @@ public class PDOMProviderTests extends PDOMTestBase { public IPath getLocation() { return new Path(tempPDOM.getAbsolutePath()); } - } }; } + @Override - public boolean providesFor(ICProject project) - throws CoreException { + public boolean providesFor(ICProject project) throws CoreException { return cproject2.equals(project); } - } )); IIndex index= CCorePlugin.getIndexManager().getIndex(cproject2, A_FRAGMENT_OPTIONS); @@ -122,13 +118,11 @@ public class PDOMProviderTests extends PDOMTestBase { } }, null); assertEquals(2, bindings.length); - } - finally { + } finally { index.releaseReadLock(); } } - public void testCommonSDK() throws Exception { final File tempPDOM= File.createTempFile("foo", "bar"); @@ -162,14 +156,11 @@ public class PDOMProviderTests extends PDOMTestBase { TestSourceReader.createFile(cproject2.getProject(), new Path("/source.cpp"), "namespace X { class A {}; }\n\n"); CCorePlugin.getIndexManager().joinIndexer(3000, npm()); - - IndexProviderManager ipm= CCoreInternals.getPDOMManager().getIndexProviderManager(); ipm.addIndexProvider(new ReadOnlyPDOMProviderBridge( new IReadOnlyPDOMProvider() { @Override - public IPDOMDescriptor[] getDescriptors( - ICConfigurationDescription config) { + public IPDOMDescriptor[] getDescriptors(ICConfigurationDescription config) { return new IPDOMDescriptor[] { new IPDOMDescriptor() { @Override @@ -181,13 +172,12 @@ public class PDOMProviderTests extends PDOMTestBase { public IPath getLocation() { return new Path(tempPDOM.getAbsolutePath()); } - } }; } + @Override - public boolean providesFor(ICProject project) - throws CoreException { + public boolean providesFor(ICProject project) throws CoreException { return cproject2.equals(project) || cproject3.equals(project); } } @@ -207,8 +197,7 @@ public class PDOMProviderTests extends PDOMTestBase { } }, null); assertEquals(2, bindings.length); - } - finally { + } finally { index.releaseReadLock(); } } @@ -227,8 +216,7 @@ public class PDOMProviderTests extends PDOMTestBase { } }, null); assertEquals(2, bindings.length); - } - finally { + } finally { index.releaseReadLock(); } } @@ -247,7 +235,6 @@ public class PDOMProviderTests extends PDOMTestBase { } }, null); assertEquals(3, bindings.length); - } finally { index.releaseReadLock(); } @@ -259,8 +246,7 @@ public class PDOMProviderTests extends PDOMTestBase { */ public void testVersionMismatchOfExternalPDOM() throws Exception { final File tempPDOM= File.createTempFile("foo", "bar"); - - + { ICProject cproject= CProjectHelper.createCCProject("foo"+System.currentTimeMillis(), null, IPDOMManager.ID_FAST_INDEXER); TestSourceReader.createFile(cproject.getProject(), new Path("/this.h"), "class A {};\n\n"); @@ -289,8 +275,7 @@ public class PDOMProviderTests extends PDOMTestBase { ipm.addIndexProvider(new ReadOnlyPDOMProviderBridge( new IReadOnlyPDOMProvider() { @Override - public IPDOMDescriptor[] getDescriptors( - ICConfigurationDescription config) { + public IPDOMDescriptor[] getDescriptors(ICConfigurationDescription config) { return new IPDOMDescriptor[] { new IPDOMDescriptor() { @Override @@ -306,9 +291,9 @@ public class PDOMProviderTests extends PDOMTestBase { } }; } + @Override - public boolean providesFor(ICProject project) - throws CoreException { + public boolean providesFor(ICProject project) throws CoreException { return cproject2.equals(project); } } @@ -316,11 +301,10 @@ public class PDOMProviderTests extends PDOMTestBase { setExpectedNumberOfLoggedNonOKStatusObjects(1); // (this applies to the entire test duration) - for(int i=0; i<3; i++) { + for (int i= 0; i < 3; i++) { // try several times in order to test the status is logged only once ICProjectDescription pd= CCorePlugin.getDefault().getProjectDescription(cproject2.getProject(), false); assertEquals(0, ipm.getProvidedIndexFragments(pd.getActiveConfiguration(), -1).length); } - } } diff --git a/core/org.eclipse.cdt.core/.settings/.api_filters b/core/org.eclipse.cdt.core/.settings/.api_filters index 543278bb554..b93964e5a8c 100644 --- a/core/org.eclipse.cdt.core/.settings/.api_filters +++ b/core/org.eclipse.cdt.core/.settings/.api_filters @@ -1,68 +1,153 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Util.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Util.java index 1e56bd13d00..655a190324c 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Util.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Util.java @@ -1,21 +1,20 @@ /******************************************************************************* - * Copyright (c) 2002, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html + * Copyright (c) 2002, 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 + * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: - * Rational Software - Initial API and implementation - * Markus Schorn (Wind River Systems) - * Anton Leherbauer (Wind River Systems) - * IBM Corporation - EFS support + * Contributors: + * Rational Software - Initial API and implementation + * Markus Schorn (Wind River Systems) + * Anton Leherbauer (Wind River Systems) + * IBM Corporation - EFS support *******************************************************************************/ package org.eclipse.cdt.internal.core.model; import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -129,31 +128,6 @@ public class Util implements ICLogConstants { return contents; } - public static void save(StringBuffer buffer, IFile file) - throws CoreException { - String encoding = null; - try { - encoding = file.getCharset(); - } catch (CoreException ce) { - // use no encoding - } - - byte[] bytes = null; - if (encoding != null) { - try { - bytes = buffer.toString().getBytes(encoding); - } catch (Exception e) { - } - } else { - bytes = buffer.toString().getBytes(); - } - - ByteArrayInputStream stream = new ByteArrayInputStream(bytes); - // use a platform operation to update the resource contents - boolean force = true; - file.setContents(stream, force, true, null); // record history - } - /** * Returns the given file's contents as a character array. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTGotoStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTGotoStatement.java index 29eaec67a21..7deee6c436a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTGotoStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTGotoStatement.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Doug Schaefer (IBM) - Initial API and implementation + * Doug Schaefer (IBM) - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; @@ -17,8 +17,8 @@ package org.eclipse.cdt.core.dom.ast; * @noimplement This interface is not intended to be implemented by clients. */ public interface IASTGotoStatement extends IASTStatement, IASTNameOwner { - - public static final ASTNodeProperty NAME = new ASTNodeProperty("IASTGotoStatement.NAME - Name for IASTGotoStatement"); //$NON-NLS-1$ + public static final ASTNodeProperty NAME = + new ASTNodeProperty("IASTGotoStatement.NAME - Name for IASTGotoStatement"); //$NON-NLS-1$ /** * Returns the name of the label. The name resolves to a ILabel binding. @@ -46,5 +46,4 @@ public interface IASTGotoStatement extends IASTStatement, IASTNameOwner { */ @Override public IASTGotoStatement copy(CopyStyle style); - } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTLabelStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTLabelStatement.java index 78fda58a327..92dc5fe6c6a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTLabelStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTLabelStatement.java @@ -21,7 +21,7 @@ public interface IASTLabelStatement extends IASTStatement, IASTNameOwner { public static final IASTStatement[] EMPTY_LABEL_STATEMENT_ARRAY = {}; public static final ASTNodeProperty NAME = new ASTNodeProperty("IASTLabelStatement.NAME - name for IASTLabelStatement"); //$NON-NLS-1$ - public static final ASTNodeProperty NESTED_STATEMENT = new ASTNodeProperty( "IASTLabelStatement.NESTED_STATEMENT - statement for IASTLabelStatement" ); //$NON-NLS-1$ + public static final ASTNodeProperty NESTED_STATEMENT = new ASTNodeProperty("IASTLabelStatement.NESTED_STATEMENT - statement for IASTLabelStatement"); //$NON-NLS-1$ /** * The name for the label. The name resolves to an ILabel binding. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java index 7ec5a145ce7..62b6d4ea1ce 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java @@ -6,8 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Doug Schaefer - Initial API and implementation - * Markus Schorn (Wind River Systems) + * Doug Schaefer - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; @@ -24,9 +24,7 @@ import org.eclipse.cdt.core.parser.IToken; * @noextend This interface is not intended to be extended by clients. */ public interface IASTNode { - /** - * @since 5.3 - */ + /** @since 5.3 */ public enum CopyStyle { /** * Copy without location, this copy is independent of the index and can be shared. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java index 4d43ae174ea..8c560e483a1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java @@ -421,13 +421,30 @@ public abstract class ArrayUtil { } /** - * Note that this should only be used when the placement of nulls within the array - * is unknown (due to performance efficiency). - * + * Moves all null elements to the end of the array. The order of non-null elements is preserved. + * @since 5.4 + */ + public static void compact(Object[] array) { + int j = 0; + for (int i = 0; i < array.length; i++) { + if (array[i] != null) { + if (j != i) { + array[j] = array[i]; + array[i] = null; + } + j++; + } + } + } + + /** * Removes all of the nulls from the array and returns a new array that contains all * of the non-null elements. * * If there are no nulls in the original array then the original array is returned. + + * Note that this method should only be used when the placement of nulls within the array + * is unknown (due to performance efficiency). */ @SuppressWarnings("unchecked") public static T[] removeNulls(Class c, T[] array) { @@ -455,13 +472,13 @@ public abstract class ArrayUtil { } /** - * Note that this should only be used when the placement of nulls within the array - * is unknown (due to performance efficiency). - * * Removes all of the nulls from the array and returns a new array that contains all * of the non-null elements. * * If there are no nulls in the original array then the original array is returned. + * + * Note that this method should only be used when the placement of nulls within the array + * is unknown (due to performance efficiency). * @since 5.2 */ @SuppressWarnings("unchecked") @@ -598,29 +615,9 @@ public abstract class ArrayUtil { } } - static public int[] setInt(int[] array, int idx, int val) { - if (array == null) { - array = new int[DEFAULT_LENGTH > idx + 1 ? DEFAULT_LENGTH : idx + 1]; - array[idx] = val; - return array; - } - - if (array.length <= idx) { - int newLen = array.length * 2; - while (newLen <= idx) - newLen *= 2; - int[] temp = new int[newLen]; - System.arraycopy(array, 0, temp, 0, array.length); - - array = temp; - } - array[idx] = val; - return array; - } - /** - * Stores the specified array contents in a new array of specified - * runtime type. + * Stores the specified array contents in a new array of specified runtime type. + * * @param target the runtime type of the new array * @param source the source array * @return the current array stored in a new array with the specified runtime type, @@ -682,4 +679,24 @@ public abstract class ArrayUtil { } return newArgs; } + + public static int[] setInt(int[] array, int idx, int val) { + if (array == null) { + array = new int[DEFAULT_LENGTH > idx + 1 ? DEFAULT_LENGTH : idx + 1]; + array[idx] = val; + return array; + } + + if (array.length <= idx) { + int newLen = array.length * 2; + while (newLen <= idx) + newLen *= 2; + int[] temp = new int[newLen]; + System.arraycopy(array, 0, temp, 0, array.length); + + array = temp; + } + array[idx] = val; + return array; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTContinueStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTContinueStatement.java index a1dfa309ece..86a42fa09d3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTContinueStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTContinueStatement.java @@ -6,8 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Rational Software - Initial API and implementation - * Yuan Zhang / Beth Tibbitts (IBM Research) + * IBM Rational Software - Initial API and implementation + * Yuan Zhang / Beth Tibbitts (IBM Research) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; @@ -19,21 +19,20 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode; * @author jcamelon */ public class CASTContinueStatement extends ASTNode implements IASTContinueStatement { - @Override - public boolean accept( ASTVisitor action ){ - if( action.shouldVisitStatements ){ - switch( action.visit( this ) ){ - case ASTVisitor.PROCESS_ABORT : return false; - case ASTVisitor.PROCESS_SKIP : return true; - default : break; + public boolean accept(ASTVisitor action) { + if (action.shouldVisitStatements) { + switch (action.visit(this)) { + case ASTVisitor.PROCESS_ABORT: return false; + case ASTVisitor.PROCESS_SKIP: return true; + default: break; } } - if( action.shouldVisitStatements ){ - switch( action.leave( this ) ){ - case ASTVisitor.PROCESS_ABORT : return false; - case ASTVisitor.PROCESS_SKIP : return true; - default : break; + if (action.shouldVisitStatements) { + switch (action.leave(this)) { + case ASTVisitor.PROCESS_ABORT: return false; + case ASTVisitor.PROCESS_SKIP: return true; + default: break; } } return true; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLabelStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLabelStatement.java index 376bbc29041..bce0038329d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLabelStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLabelStatement.java @@ -6,8 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Rational Software - Initial API and implementation - * Yuan Zhang / Beth Tibbitts (IBM Research) + * IBM Rational Software - Initial API and implementation + * Yuan Zhang / Beth Tibbitts (IBM Research) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; @@ -23,10 +23,8 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; * @author jcamelon */ public class CASTLabelStatement extends ASTNode implements IASTLabelStatement, IASTAmbiguityParent { - private IASTName name; private IASTStatement nestedStatement; - public CASTLabelStatement() { } @@ -69,30 +67,30 @@ public class CASTLabelStatement extends ASTNode implements IASTLabelStatement, I } @Override - public boolean accept( ASTVisitor action ){ - if( action.shouldVisitStatements ){ - switch( action.visit( this ) ){ - case ASTVisitor.PROCESS_ABORT : return false; - case ASTVisitor.PROCESS_SKIP : return true; - default : break; + public boolean accept(ASTVisitor action) { + if (action.shouldVisitStatements) { + switch (action.visit(this)) { + case ASTVisitor.PROCESS_ABORT: return false; + case ASTVisitor.PROCESS_SKIP: return true; + default: break; } } - if( name != null ) if( !name.accept( action ) ) return false; - if( nestedStatement != null ) if( !nestedStatement.accept( action ) ) return false; - if( action.shouldVisitStatements ){ - switch( action.leave( this ) ){ - case ASTVisitor.PROCESS_ABORT : return false; - case ASTVisitor.PROCESS_SKIP : return true; - default : break; + if (name != null && !name.accept(action)) return false; + if (nestedStatement != null && !nestedStatement.accept(action)) return false; + if (action.shouldVisitStatements) { + switch (action.leave(this)) { + case ASTVisitor.PROCESS_ABORT: return false; + case ASTVisitor.PROCESS_SKIP: return true; + default: break; } } return true; } - @Override public int getRoleForName(IASTName n) { - if( n == name ) return r_declaration; + if (n == name) + return r_declaration; return r_unclear; } @@ -113,12 +111,10 @@ public class CASTLabelStatement extends ASTNode implements IASTLabelStatement, I @Override public void replace(IASTNode child, IASTNode other) { - if( child == nestedStatement ) - { - other.setParent( this ); - other.setPropertyInParent( child.getPropertyInParent() ); + if (child == nestedStatement) { + other.setParent(this); + other.setPropertyInParent(child.getPropertyInParent()); setNestedStatement((IASTStatement) other); } } - } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLiteralExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLiteralExpression.java index ec632f68e43..8e0f15927d7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLiteralExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLiteralExpression.java @@ -6,9 +6,9 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * John Camelon (IBM Rational Software) - Initial API and implementation - * Yuan Zhang / Beth Tibbitts (IBM Research) - * Markus Schorn (Wind River Systems) + * John Camelon (IBM Rational Software) - Initial API and implementation + * Yuan Zhang / Beth Tibbitts (IBM Research) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; @@ -26,7 +26,6 @@ import org.eclipse.cdt.internal.core.dom.parser.ProblemType; * Represents a literal */ public class CASTLiteralExpression extends ASTNode implements IASTLiteralExpression { - private int kind; private char[] value = CharArrayUtils.EMPTY; @@ -81,24 +80,24 @@ public class CASTLiteralExpression extends ASTNode implements IASTLiteralExpress } @Override - public boolean accept( ASTVisitor action ){ - if( action.shouldVisitExpressions ){ - switch( action.visit( this ) ){ - case ASTVisitor.PROCESS_ABORT : return false; - case ASTVisitor.PROCESS_SKIP : return true; - default : break; + public boolean accept(ASTVisitor action) { + if (action.shouldVisitExpressions) { + switch (action.visit(this)) { + case ASTVisitor.PROCESS_ABORT: return false; + case ASTVisitor.PROCESS_SKIP: return true; + default: break; } } - if( action.shouldVisitExpressions ){ - switch( action.leave( this ) ){ - case ASTVisitor.PROCESS_ABORT : return false; - case ASTVisitor.PROCESS_SKIP : return true; - default : break; + if (action.shouldVisitExpressions) { + switch (action.leave(this)) { + case ASTVisitor.PROCESS_ABORT: return false; + case ASTVisitor.PROCESS_SKIP: return true; + default: break; } } return true; } - + @Override public IType getExpressionType() { switch (getKind()) { @@ -141,7 +140,7 @@ public class CASTLiteralExpression extends ASTNode implements IASTLiteralExpress break; } } - + return new CBasicType(kind, flags, this); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTWhileStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTWhileStatement.java index ba564d57f3a..c34ac0de762 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTWhileStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTWhileStatement.java @@ -6,8 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Rational Software - Initial API and implementation - * Yuan Zhang / Beth Tibbitts (IBM Research) + * IBM Rational Software - Initial API and implementation + * Yuan Zhang / Beth Tibbitts (IBM Research) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; @@ -23,11 +23,9 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; * @author jcamelon */ public class CASTWhileStatement extends ASTNode implements IASTWhileStatement, IASTAmbiguityParent { - private IASTExpression condition; private IASTStatement body; - public CASTWhileStatement() { } @@ -84,22 +82,22 @@ public class CASTWhileStatement extends ASTNode implements IASTWhileStatement, I } @Override - public boolean accept( ASTVisitor action ){ - if( action.shouldVisitStatements ){ - switch( action.visit( this ) ){ - case ASTVisitor.PROCESS_ABORT : return false; - case ASTVisitor.PROCESS_SKIP : return true; - default : break; + public boolean accept(ASTVisitor action) { + if (action.shouldVisitStatements) { + switch (action.visit(this)) { + case ASTVisitor.PROCESS_ABORT: return false; + case ASTVisitor.PROCESS_SKIP: return true; + default: break; } } - if( condition != null ) if( !condition.accept( action ) ) return false; - if( body != null ) if( !body.accept( action ) ) return false; + if (condition != null && !condition.accept(action)) return false; + if (body != null && !body.accept(action)) return false; - if( action.shouldVisitStatements ){ - switch( action.leave( this ) ){ - case ASTVisitor.PROCESS_ABORT : return false; - case ASTVisitor.PROCESS_SKIP : return true; - default : break; + if (action.shouldVisitStatements) { + switch (action.leave(this)) { + case ASTVisitor.PROCESS_ABORT: return false; + case ASTVisitor.PROCESS_SKIP: return true; + default: break; } } return true; @@ -107,16 +105,14 @@ public class CASTWhileStatement extends ASTNode implements IASTWhileStatement, I @Override public void replace(IASTNode child, IASTNode other) { - if( body == child ) - { - other.setPropertyInParent( child.getPropertyInParent() ); - other.setParent( child.getParent() ); + if (body == child) { + other.setPropertyInParent(child.getPropertyInParent()); + other.setParent(child.getParent()); body = (IASTStatement) other; } - if( child == condition ) - { - other.setPropertyInParent( child.getPropertyInParent() ); - other.setParent( child.getParent() ); + if (child == condition) { + other.setPropertyInParent(child.getPropertyInParent()); + other.setParent(child.getParent()); condition = (IASTExpression) other; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTContinueStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTContinueStatement.java index 0d1915fbcbe..f2bf12eeb03 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTContinueStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTContinueStatement.java @@ -18,7 +18,6 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode; * @author jcamelon */ public class CPPASTContinueStatement extends ASTNode implements IASTContinueStatement { - @Override public boolean accept(ASTVisitor action) { if (action.shouldVisitStatements) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index b1ecf3efe0d..8d1b457375b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -1812,7 +1812,7 @@ public class CPPSemantics { return new CPPCompositeBinding(result); } - static public boolean declaredBefore(Object obj, IASTNode node, boolean indexBased) { + public static boolean declaredBefore(Object obj, IASTNode node, boolean indexBased) { if (node == null) return true; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncher.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncher.java index a0f99e68736..dd7c0d68023 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncher.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncher.java @@ -15,31 +15,34 @@ import java.io.IOException; import java.io.OutputStream; import java.util.Properties; +import org.eclipse.cdt.internal.core.Cygwin; import org.eclipse.cdt.internal.core.ProcessClosure; +import org.eclipse.cdt.utils.PathUtil; import org.eclipse.cdt.utils.spawner.EnvironmentReader; import org.eclipse.cdt.utils.spawner.ProcessFactory; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Platform; /** * @noextend This class is not intended to be subclassed by clients. */ public class CommandLauncher implements ICommandLauncher { - public final static int COMMAND_CANCELED = ICommandLauncher.COMMAND_CANCELED; public final static int ILLEGAL_COMMAND = ICommandLauncher.ILLEGAL_COMMAND; public final static int OK = ICommandLauncher.OK; + private static final String PATH_ENV = "PATH"; //$NON-NLS-1$ + private static final String NEWLINE = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ protected Process fProcess; protected boolean fShowCommand; protected String[] fCommandArgs; + private Properties fEnvironment = null; protected String fErrorMessage = ""; //$NON-NLS-1$ - - private String lineSeparator; private IProject fProject; /** @@ -55,7 +58,6 @@ public class CommandLauncher implements ICommandLauncher { public CommandLauncher() { fProcess = null; fShowCommand = false; - lineSeparator = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ } /* (non-Javadoc) @@ -95,7 +97,11 @@ public class CommandLauncher implements ICommandLauncher { */ @Override public Properties getEnvironment() { - return EnvironmentReader.getEnvVars(); + if (fEnvironment == null) { + // for backward compatibility, note that this return may be not accurate + return EnvironmentReader.getEnvVars(); + } + return fEnvironment; } /* (non-Javadoc) @@ -116,6 +122,23 @@ public class CommandLauncher implements ICommandLauncher { return args; } + /** + * Parse array of "ENV=value" pairs to Properties. + */ + private Properties parseEnv(String[] env) { + Properties envProperties = new Properties(); + for (String envStr : env) { + // Split "ENV=value" and put in Properties + int pos = envStr.indexOf('='); + if (pos < 0) + pos = envStr.length(); + String key = envStr.substring(0, pos); + String value = envStr.substring(pos + 1); + envProperties.put(key, value); + } + return envProperties; + } + /** * @deprecated * @since 5.1 @@ -123,42 +146,65 @@ public class CommandLauncher implements ICommandLauncher { @Deprecated public Process execute(IPath commandPath, String[] args, String[] env, IPath changeToDirectory) { try { - // add platform specific arguments (shell invocation) - fCommandArgs = constructCommandArray(commandPath.toOSString(), args); - - File file = null; - - if(changeToDirectory != null) - file = changeToDirectory.toFile(); - - fProcess = ProcessFactory.getFactory().exec(fCommandArgs, env, file); - fErrorMessage = ""; //$NON-NLS-1$ - } catch (IOException e) { - setErrorMessage(e.getMessage()); - fProcess = null; + return execute(commandPath, args, env, changeToDirectory, null); + } catch (CoreException e) { + CCorePlugin.log(e); } - return fProcess; + return null; } + /** * @since 5.1 * @see org.eclipse.cdt.core.ICommandLauncher#execute(IPath, String[], String[], IPath, IProgressMonitor) */ @Override - public Process execute(IPath commandPath, String[] args, String[] env, IPath changeToDirectory, IProgressMonitor monitor) throws CoreException { + public Process execute(IPath commandPath, String[] args, String[] env, IPath workingDirectory, IProgressMonitor monitor) throws CoreException { + Boolean isFound = null; + String command = commandPath.toOSString(); + String envPathValue = (String) getEnvironment().get(PATH_ENV); try { - // add platform specific arguments (shell invocation) - fCommandArgs = constructCommandArray(commandPath.toOSString(), args); + fCommandArgs = constructCommandArray(command, args); + if (Platform.getOS().equals(Platform.OS_WIN32)) { + // Handle cygwin link + IPath location = PathUtil.findProgramLocation(command, envPathValue); + isFound = location != null; + if (location != null) { + try { + fCommandArgs[0] = Cygwin.cygwinToWindowsPath(location.toString(), envPathValue); + } catch (Exception e) { + // if no cygwin nothing to worry about + } + } + } - File file = null; + fEnvironment = parseEnv(env); + File dir = workingDirectory != null ? workingDirectory.toFile() : null; - if(changeToDirectory != null) - file = changeToDirectory.toFile(); - - fProcess = ProcessFactory.getFactory().exec(fCommandArgs, env, file); + fProcess = ProcessFactory.getFactory().exec(fCommandArgs, env, dir); + fCommandArgs[0] = command; // to print original command on the console fErrorMessage = ""; //$NON-NLS-1$ } catch (IOException e) { - setErrorMessage(e.getMessage()); + if (isFound == null) { + IPath location = PathUtil.findProgramLocation(command, envPathValue); + isFound = location != null; + } + + String errorMessage = getCommandLineQuoted(fCommandArgs, true); + String exMsg = e.getMessage(); + if (exMsg != null && !exMsg.isEmpty()) { + errorMessage = errorMessage + exMsg + NEWLINE; + } + + if (!isFound) { + if (envPathValue == null) { + envPathValue = System.getenv(PATH_ENV); + } + errorMessage = errorMessage + NEWLINE + + "Error: Program \"" + command + "\" not found in PATH" + NEWLINE + + "PATH=[" + envPathValue + "]" + NEWLINE; + } + setErrorMessage(errorMessage); fProcess = null; } return fProcess; @@ -168,6 +214,7 @@ public class CommandLauncher implements ICommandLauncher { * @see org.eclipse.cdt.core.ICommandLauncher#waitAndRead(java.io.OutputStream, java.io.OutputStream) */ @Override + @Deprecated public int waitAndRead(OutputStream out, OutputStream err) { if (fShowCommand) { printCommandLine(out); @@ -224,9 +271,8 @@ public class CommandLauncher implements ICommandLauncher { protected void printCommandLine(OutputStream os) { if (os != null) { - String cmd = getCommandLine(getCommandArgs()); try { - os.write(cmd.getBytes()); + os.write(getCommandLineQuoted(getCommandArgs(), true).getBytes()); os.flush(); } catch (IOException e) { // ignore; @@ -234,18 +280,26 @@ public class CommandLauncher implements ICommandLauncher { } } - protected String getCommandLine(String[] commandArgs) { + @SuppressWarnings("nls") + private String getCommandLineQuoted(String[] commandArgs, boolean quote) { StringBuffer buf = new StringBuffer(); - if (fCommandArgs != null) { + if (commandArgs != null) { for (String commandArg : commandArgs) { + if (quote && (commandArg.contains(" ") || commandArg.contains("\"") || commandArg.contains("\\"))) { + commandArg = '"' + commandArg.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"") + '"'; + } buf.append(commandArg); buf.append(' '); } - buf.append(lineSeparator); + buf.append(NEWLINE); } return buf.toString(); } + protected String getCommandLine(String[] commandArgs) { + return getCommandLineQuoted(commandArgs, false); + } + /** * @since 5.1 diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICommandLauncher.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICommandLauncher.java index 57a04880ed8..d6dc229aa41 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICommandLauncher.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ICommandLauncher.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -20,7 +20,7 @@ import org.eclipse.core.runtime.IProgressMonitor; /** * An interface for launchers of external commands. - * + * * @since 5.1 */ public interface ICommandLauncher { @@ -28,19 +28,19 @@ public interface ICommandLauncher { public final static int COMMAND_CANCELED = 1; public final static int ILLEGAL_COMMAND = -1; public final static int OK = 0; - - + + /** * Sets the project that this launcher is associated with, or null if there is no such * project. - * + * * @param project */ public void setProject(IProject project); - + /** * Gets the project this launcher is associated with. - * + * * @return IProject, or null if there is no such project. */ public IProject getProject(); @@ -53,15 +53,16 @@ public interface ICommandLauncher { /** * Returns a human readable error message corresponding to the last error encountered during command * execution. - * + * * @return A String corresponding to the error, or null if there has been no error. + * The message could be multi-line, however it is NOT guaranteed that it ends with end of line. */ public String getErrorMessage(); /** * Sets the human readable error message corresponding to the last error encountered during command * execution. A subsequent call to getErrorMessage() will return this string. - * + * * @param error A String corresponding to the error message, or null if the error state is * intended to be cleared. */ @@ -69,7 +70,7 @@ public interface ICommandLauncher { /** * Returns an array of the command line arguments that were last used to execute a command. - * + * * @return an array of type String[] corresponding to the arguments. The array can be empty, but should not * be null. */ @@ -78,14 +79,14 @@ public interface ICommandLauncher { /** * Returns the set of environment variables in the context of which * this launcher will execute commands. - * + * * @return Properties */ public Properties getEnvironment(); /** * Returns the constructed command line of the last command executed. - * + * * @return String */ public String getCommandLine(); @@ -95,11 +96,13 @@ public interface ICommandLauncher { * @param env The list of environment variables in variable=value format. * @throws CoreException if there is an error executing the command. */ - public Process execute(IPath commandPath, String[] args, String[] env, IPath changeToDirectory, IProgressMonitor monitor) throws CoreException; + public Process execute(IPath commandPath, String[] args, String[] env, IPath workingDirectory, IProgressMonitor monitor) throws CoreException; /** * Reads output form the process to the streams. + * @deprecated Deprecated as of CDT 8.1. Use method taking IProgressMonitor instead. */ + @Deprecated public int waitAndRead(OutputStream out, OutputStream err); /** diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/RefreshExclusion.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/RefreshExclusion.java index 09d0345b4cc..71c0eedaacd 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/RefreshExclusion.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/RefreshExclusion.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 IBM Corporation and others. + * Copyright (c) 2011, 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 @@ -11,6 +11,7 @@ package org.eclipse.cdt.core.resources; import java.util.Collections; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -34,7 +35,7 @@ import com.ibm.icu.text.MessageFormat; * @since 5.3 * */ -public abstract class RefreshExclusion { +public abstract class RefreshExclusion implements Cloneable{ public static final String CLASS_ATTRIBUTE_NAME = "class"; //$NON-NLS-1$ public static final String CONTRIBUTOR_ID_ATTRIBUTE_NAME = "contributorId"; //$NON-NLS-1$ @@ -356,5 +357,42 @@ public abstract class RefreshExclusion { return currentValue; } + + /** + * Duplicate this refresh exclusion to the given one. + * @param destination - the refresh exclusion to be modified + * @since 5.4 + */ + protected void copyTo (RefreshExclusion destination) { + destination.setContributorId(getContributorId()); + destination.setExclusionType(getExclusionType()); + destination.setParentResource(getParentResource()); + + Iterator iterator = getNestedExclusions().iterator(); + while (iterator.hasNext()) { + RefreshExclusion nestedExclusion = iterator.next(); + RefreshExclusion clone; + clone = (RefreshExclusion) nestedExclusion.clone(); + clone.setParentExclusion(destination); + destination.addNestedExclusion(clone); + } + + Iterator exclusionInstances = getExclusionInstances().iterator(); + + while(exclusionInstances.hasNext()) { + ExclusionInstance next = exclusionInstances.next(); + ExclusionInstance newInstance = new ExclusionInstance(); + newInstance.setDisplayString(next.getDisplayString()); + newInstance.setExclusionType(next.getExclusionType()); + newInstance.setParentExclusion(destination); + newInstance.setResource(next.getResource()); + destination.addExclusionInstance(newInstance); + } + } + /* (non-Javadoc) + * @see java.lang.Object#clone() + */ + @Override + public abstract Object clone(); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/RefreshScopeManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/RefreshScopeManager.java index 4297cc3f0e8..559e3cf5999 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/RefreshScopeManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/RefreshScopeManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 IBM Corporation and others. + * Copyright (c) 2011, 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 @@ -10,13 +10,15 @@ *******************************************************************************/ package org.eclipse.cdt.core.resources; +import java.util.ArrayList; + import java.util.HashMap; -import java.util.LinkedHashSet; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; - import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CProjectNature; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICStorageElement; import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager; @@ -74,6 +76,14 @@ public class RefreshScopeManager { public static final String VERSION_ELEMENT_NAME = "version"; //$NON-NLS-1$ public static final String VERSION_NUMBER_ATTRIBUTE_NAME = "versionNumber"; //$NON-NLS-1$ public static final String WORKSPACE_PATH_ATTRIBUTE_NAME = "workspacePath"; //$NON-NLS-1$ + /** + * @since 5.4 + */ + public static final String CONFIGURATION_ELEMENT = "configuration"; //$NON-NLS-1$ + /** + * @since 5.4 + */ + public static final String CONFIGURATION_ELEMENT_NAME = "configurationName"; //$NON-NLS-1$ public static synchronized RefreshScopeManager getInstance() { if (fInstance == null) { @@ -87,10 +97,8 @@ public class RefreshScopeManager { private boolean fIsLoaded = false; private boolean fIsLoading = false; - private HashMap> fProjectToResourcesMap; - private HashMap> fResourceToExclusionsMap; - - private int fVersion = 1; + private HashMap>>> fProjToConfToResToExcluMap; + private int fVersion = 2; private RefreshScopeManager() { fClassnameToExclusionFactoryMap = new HashMap(); @@ -145,7 +153,6 @@ public class RefreshScopeManager { return false; } - } else if (delta.getResource() instanceof IWorkspaceRoot) { @@ -161,7 +168,6 @@ public class RefreshScopeManager { e.printStackTrace(); } } - } }, @@ -169,95 +175,82 @@ public class RefreshScopeManager { | IResourceChangeEvent.PRE_DELETE); } - public synchronized void addExclusion(IResource resource, RefreshExclusion exclusion) { - getResourcesToExclusionsMap(); + /** + * @since 5.4 + */ + public synchronized void addExclusion(IProject project, String configName, IResource resource, RefreshExclusion exclusion) { + HashMap> resourceMap = getResourcesToExclusionsMap(project,configName); - List exclusions = fResourceToExclusionsMap.get(resource); + List exclusions = resourceMap.get(resource); if (exclusions == null) { exclusions = new LinkedList(); - fResourceToExclusionsMap.put(resource, exclusions); + resourceMap.put(resource, exclusions); } - + exclusions.add(exclusion); } - public synchronized void addResourceToRefresh(IProject project, IResource resource) { - getProjectToResourcesMap(); - LinkedHashSet resourceSet = fProjectToResourcesMap.get(project); - - if (resourceSet == null) { - resourceSet = new LinkedHashSet(); - fProjectToResourcesMap.put(project, resourceSet); + /** + * @since 5.4 + */ + // We are adding a new resource. + public synchronized void addResourceToRefresh(IProject project, String configName, IResource resource) { + + HashMap> resourceMap = getResourcesToExclusionsMap(project, configName); + + if (!resourceMap.containsKey(resource)) { + // create a new one: + LinkedList exclusions = new LinkedList(); + resourceMap.put(resource, exclusions); } - - resourceSet.add(resource); - } - + public synchronized void clearAllData() { - clearAllResourcesToRefresh(); - clearAllExclusions(); + getProjectToConfigurationToResourcesMap(); + fProjToConfToResToExcluMap.clear(); fIsLoaded = false; } - public synchronized void clearAllExclusions() { - if (fResourceToExclusionsMap != null) - fResourceToExclusionsMap.clear(); - } - - public synchronized void clearAllResourcesToRefresh() { - getProjectToResourcesMap(); - fProjectToResourcesMap.clear(); - } - private synchronized void clearDataForProject(IProject project) { - clearResourcesToRefresh(project); - clearExclusionsForProject(project); + HashMap>> configMap = fProjToConfToResToExcluMap.get(project); + if (configMap != null) + configMap.clear(); } - public synchronized void clearExclusions(IResource resource) { - getResourcesToExclusionsMap(); - List exclusions = fResourceToExclusionsMap.get(resource); + /** + * @since 5.4 + */ + public synchronized void clearExclusions(IProject project, String configName, IResource resource) { + HashMap> resourceMap = getResourcesToExclusionsMap(project, configName); + List exclusions = resourceMap.get(resource); if (exclusions != null) { exclusions.clear(); } } - - public synchronized void clearExclusionsForProject(IProject project) { - getResourcesToExclusionsMap(); - List resourcesToRemove = new LinkedList(); - - for (IResource resource : fResourceToExclusionsMap.keySet()) { - IProject project2 = resource.getProject(); - if (project2.equals(project)) { - resourcesToRemove.add(resource); - } - } - - for (IResource resource : resourcesToRemove) { - fResourceToExclusionsMap.remove(resource); - } - } - + public synchronized void clearResourcesToRefresh(IProject project) { - getProjectToResourcesMap(); - LinkedHashSet resourceSet = null; + // Clear all resources for the given project. + HashMap>> configMap = getConfigurationToResourcesMap(project); + HashMap> resourceMap = null; - fProjectToResourcesMap.put(project, resourceSet); - } - - public synchronized void deleteResourceToRefresh(IProject project, IResource resource) { - getProjectToResourcesMap(); - LinkedHashSet resourceSet = fProjectToResourcesMap.get(project); - - if (resourceSet == null) { - resourceSet = new LinkedHashSet(); - return; + Iterator it = configMap.keySet().iterator(); + while (it.hasNext()) { + String configName = it.next(); + resourceMap = configMap.get(configName); + resourceMap.clear(); } - - resourceSet.remove(resource); } + /** + * @since 5.4 + */ + public synchronized void deleteResourceToRefresh(IProject project, String configName, IResource resource) { + HashMap> resourceMap = getResourcesToExclusionsMap(project, configName); + + if (resourceMap.containsKey(resource)) + resourceMap.remove(resource); + } + public synchronized RefreshExclusion getExclusionForClassName(String className) { RefreshExclusionFactory factory = getFactoryForClassName(className); @@ -268,17 +261,6 @@ public class RefreshScopeManager { return factory.createNewExclusion(); } - public synchronized List getExclusions(IResource resource) { - getResourcesToExclusionsMap(); - List exclusions = fResourceToExclusionsMap.get(resource); - if (exclusions == null) { - exclusions = new LinkedList(); - fResourceToExclusionsMap.put(resource, exclusions); - } - - return exclusions; - } - public synchronized RefreshExclusionFactory getFactoryForClassName(String className) { RefreshExclusionFactory factory = fClassnameToExclusionFactoryMap.get(className); @@ -295,16 +277,47 @@ public class RefreshScopeManager { return factory.createNewExclusionInstance(); } - private HashMap> getProjectToResourcesMap() { - if (fProjectToResourcesMap == null) { - fProjectToResourcesMap = new HashMap>(); + private HashMap> getResourcesToExclusionsMap(IProject project, String configName) { + getProjectToConfigurationToResourcesMap(); + HashMap>> configMap = getConfigurationToResourcesMap(project); + HashMap> resourceMap = configMap.get(configName); + + if (resourceMap == null) { + resourceMap = new HashMap>(); + resourceMap.put(project, new LinkedList()); + configMap.put(configName, resourceMap); } - - return fProjectToResourcesMap; + + return resourceMap; } + /** + * @since 5.4 + */ + public synchronized HashMap>> getConfigurationToResourcesMap(IProject project) + { + getProjectToConfigurationToResourcesMap(); + HashMap>> configMap = fProjToConfToResToExcluMap.get(project); + + if (configMap == null) { + configMap = new HashMap>>(); + fProjToConfToResToExcluMap.put(project,configMap); + } + + return configMap; + + } + + private HashMap>>> getProjectToConfigurationToResourcesMap() { + if (fProjToConfToResToExcluMap == null) { + fProjToConfToResToExcluMap = new HashMap>>>(); + } + + return fProjToConfToResToExcluMap; + } + + public IWorkspaceRunnable getRefreshRunnable(final IProject project) { - IWorkspaceRunnable runnable = new IWorkspaceRunnable() { /** @@ -312,18 +325,18 @@ public class RefreshScopeManager { * @param resource * @throws CoreException */ - private void refreshResources(IResource resource, List exclusions, + private void refreshResources(String configName, IResource resource, List exclusions, IProgressMonitor monitor) throws CoreException { if (resource instanceof IContainer) { IContainer container = (IContainer) resource; - if (shouldResourceBeRefreshed(resource)) { + if (shouldResourceBeRefreshed(configName, resource)) { resource.refreshLocal(IResource.DEPTH_ONE, monitor); } for (IResource child : container.members()) { - refreshResources(child, exclusions, monitor); + refreshResources(configName, child, exclusions, monitor); } } } @@ -331,51 +344,40 @@ public class RefreshScopeManager { @Override public void run(IProgressMonitor monitor) throws CoreException { - List resourcesToRefresh = getResourcesToRefresh(project); - for (IResource resource : resourcesToRefresh) { - List exclusions = getExclusions(resource); - refreshResources(resource, exclusions, monitor); - } + HashMap>> configMap = getConfigurationToResourcesMap(project); + Iterator it = configMap.keySet().iterator(); + while (it.hasNext()) { + String configName = it.next(); + List resourcesToRefresh = getResourcesToRefresh(project,configName); + for (IResource resource : resourcesToRefresh) { + List exclusions = getExclusions(project,configName,resource); + refreshResources(configName, resource, exclusions, monitor); + } + } } }; return runnable; } - public synchronized ISchedulingRule getRefreshSchedulingRule(IProject project) { - return new MultiRule(getResourcesToRefresh(project).toArray(new ISchedulingRule[0])); - } - - private HashMap> getResourcesToExclusionsMap() { - if (fResourceToExclusionsMap == null) { - fResourceToExclusionsMap = new HashMap>(); - } - - return fResourceToExclusionsMap; + /** + * @since 5.4 + */ + public synchronized ISchedulingRule getRefreshSchedulingRule(IProject project, String configName) { + return new MultiRule(getResourcesToRefresh(project, configName).toArray(new ISchedulingRule[0])); } /** - * Returns the set of resources that should be refreshed for a project. These resources might have - * associated exclusions. - * - * @param project - * @return List + * @since 5.4 */ - public synchronized List getResourcesToRefresh(IProject project) { - getProjectToResourcesMap(); - LinkedHashSet resources = fProjectToResourcesMap.get(project); + public synchronized List getResourcesToRefresh(IProject project, String configName) { + getProjectToConfigurationToResourcesMap(); - if (resources == null) { - // there are no settings yet for the project, setup the defaults - resources = new LinkedHashSet(); - resources.add(project); - fProjectToResourcesMap.put(project, resources); - } - - return new LinkedList(resources); + HashMap> resourceMap = getResourcesToExclusionsMap(project,configName); + return new ArrayList(resourceMap.keySet()); } - + public int getVersion() { return fVersion; } @@ -465,79 +467,105 @@ public class RefreshScopeManager { REFRESH_SCOPE_STORAGE_NAME, true); // walk the tree and load the settings - - // for now ignore the version attribute, as we only have version 1 at this time + + String str = storageElement.getAttribute(VERSION_NUMBER_ATTRIBUTE_NAME); + int version = (str != null) ? Integer.valueOf(str) : 2; // iterate through the child nodes ICStorageElement[] children = storageElement.getChildren(); - for (ICStorageElement child : children) { + if (version == 1) { + ICConfigurationDescription cfgDescs[] = projectDescription.getConfigurations(); + for (ICConfigurationDescription cfgDesc : cfgDescs) + loadResourceData(workspaceRoot, project, cfgDesc.getName(), children); + + } else { + for (ICStorageElement child : children) { + if (child.getName().equals(CONFIGURATION_ELEMENT) ) { + String configName = child.getAttribute(CONFIGURATION_ELEMENT_NAME); + loadResourceData(workspaceRoot, project, configName, child.getChildren()); + } + } + } + } + } + } - if (child.getName().equals(RESOURCE_ELEMENT_NAME)) { + /** + * @since 5.4 + */ + public synchronized void loadResourceData(IWorkspaceRoot workspaceRoot, IProject project, String configName, ICStorageElement[] children) { + + for (ICStorageElement child : children) { + if (child.getName().equals(RESOURCE_ELEMENT_NAME)) { + + // get the resource path + String resourcePath = child.getAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME); + + if (resourcePath == null) { + // error... skip this resource + continue; + + } + + else { + String resourceTypeString = child + .getAttribute(RESOURCE_TYPE_ATTRIBUTE_NAME); + + if (resourceTypeString == null) { + // we'll do our best, but we won't be able to create handles to non-existent + // resources + resourceTypeString = OTHER_VALUE; + } + + // find the resource + IResource resource = null; + + if (resourceTypeString.equals(PROJECT_VALUE)) { + resource = workspaceRoot.getProject(resourcePath); + } + + else if (resourceTypeString.equals(FILE_VALUE)) { + resource = workspaceRoot.getFile(new Path(resourcePath)); + } + + else if (resourceTypeString.equals(FOLDER_VALUE)) { + resource = workspaceRoot.getFolder(new Path(resourcePath)); + } + + else { + // Find arbitrary resource. + // The only way to do this is to ask the workspace root to find + // it, if it exists. If it doesn't exist, we have no way of + // creating a handle to the right type of object, so we must + // give up. In practice, this would likely happen if we had + // a virtual group resource that has been deleted somehow since + // the settings were created, and since the resource is virtual, + // it's impossible to refresh it if it doesn't exist anyway. + resource = workspaceRoot.findMember(resourcePath); + } + + if (resource == null) { + // error.. skip this resource + continue; + } + + else { + addResourceToRefresh(project,configName, resource); + + // load any exclusions + List exclusions; + try { + exclusions = RefreshExclusion.loadData( + child, null, resource, this); - // get the resource path - String resourcePath = child.getAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME); - - if (resourcePath == null) { - // error... skip this resource - continue; - - } - - else { - String resourceTypeString = child - .getAttribute(RESOURCE_TYPE_ATTRIBUTE_NAME); - - if (resourceTypeString == null) { - // we'll do our best, but we won't be able to create handles to non-existent - // resources - resourceTypeString = OTHER_VALUE; - } - - // find the resource - IResource resource = null; - - if (resourceTypeString.equals(PROJECT_VALUE)) { - resource = workspaceRoot.getProject(resourcePath); - } - - else if (resourceTypeString.equals(FILE_VALUE)) { - resource = workspaceRoot.getFile(new Path(resourcePath)); - } - - else if (resourceTypeString.equals(FOLDER_VALUE)) { - resource = workspaceRoot.getFolder(new Path(resourcePath)); - } - - else { - // Find arbitrary resource. - // The only way to do this is to ask the workspace root to find - // it, if it exists. If it doesn't exist, we have no way of - // creating a handle to the right type of object, so we must - // give up. In practice, this would likely happen if we had - // a virtual group resource that has been deleted somehow since - // the settings were created, and since the resource is virtual, - // it's impossible to refresh it if it doesn't exist anyway. - resource = workspaceRoot.findMember(resourcePath); - } - - if (resource == null) { - // error.. skip this resource - continue; - } - - else { - addResourceToRefresh(project, resource); - - // load any exclusions - List exclusions = RefreshExclusion.loadData( - child, null, resource, this); - - // add them - for (RefreshExclusion exclusion : exclusions) { - addExclusion(resource, exclusion); - } + // add them + for (RefreshExclusion exclusion : exclusions) { + addExclusion(project, configName, resource, exclusion); } + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } } } @@ -547,14 +575,13 @@ public class RefreshScopeManager { public synchronized void persistSettings(ICProjectDescription projectDescription) throws CoreException { - getProjectToResourcesMap(); - getResourcesToExclusionsMap(); + IProject project = projectDescription.getProject(); if (!project.exists()) { return; } - + // serialize all settings for the project to the C Project Description if (project.isOpen()) { if (project.hasNature(CProjectNature.C_NATURE_ID)) { @@ -566,77 +593,139 @@ public class RefreshScopeManager { storageElement.setAttribute(VERSION_NUMBER_ATTRIBUTE_NAME, Integer.toString(fVersion)); - for (IResource resource : fProjectToResourcesMap.get(project)) { - - // create a resource node - ICStorageElement resourceElement = storageElement - .createChild(RESOURCE_ELEMENT_NAME); - resourceElement.setAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME, resource - .getFullPath().toString()); - - String resourceTypeString = null; - - if (resource instanceof IFile) { - resourceTypeString = FILE_VALUE; - } - - else if (resource instanceof IFolder) { - resourceTypeString = FOLDER_VALUE; - } - - else if (resource instanceof IProject) { - resourceTypeString = PROJECT_VALUE; - } - - else { - resourceTypeString = OTHER_VALUE; - } - - resourceElement.setAttribute(RESOURCE_TYPE_ATTRIBUTE_NAME, resourceTypeString); - - // populate the node with any exclusions - List exclusions = fResourceToExclusionsMap.get(resource); - if (exclusions != null) { - for (RefreshExclusion exclusion : exclusions) { - exclusion.persistData(resourceElement); + HashMap>> configMap = getConfigurationToResourcesMap(project); + if (!configMap.isEmpty()) { + + Iterator it = configMap.keySet().iterator(); + + while (it.hasNext()) { + String configName = it.next(); + + // for the current configuration, create a storage element + ICStorageElement configElement = storageElement.createChild(CONFIGURATION_ELEMENT); + configElement.setAttribute(CONFIGURATION_ELEMENT_NAME, configName); + + // set the resource to exclusion map for this config name. + HashMap> resourceMap = configMap.get(configName); + + // for each resource + for (IResource resource : resourceMap.keySet()) { + persistDataResource(configElement, resource,resourceMap); } - } - + } } - } } - } - public synchronized void removeExclusion(IResource resource, RefreshExclusion exclusion) { - getResourcesToExclusionsMap(); - List exclusions = fResourceToExclusionsMap.get(resource); + /** + * @since 5.4 + */ + public synchronized void persistDataResource(ICStorageElement storageElement, IResource resource, HashMap> resourceMap) { + // create a resource node + ICStorageElement resourceElement = storageElement + .createChild(RESOURCE_ELEMENT_NAME); + resourceElement.setAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME, resource + .getFullPath().toString()); + + String resourceTypeString = null; + + if (resource instanceof IFile) { + resourceTypeString = FILE_VALUE; + } + + else if (resource instanceof IFolder) { + resourceTypeString = FOLDER_VALUE; + } + + else if (resource instanceof IProject) { + resourceTypeString = PROJECT_VALUE; + } + + else { + resourceTypeString = OTHER_VALUE; + } + + resourceElement.setAttribute(RESOURCE_TYPE_ATTRIBUTE_NAME, resourceTypeString); + + // populate the node with any exclusions + List exclusions = resourceMap.get(resource); + if (exclusions != null) { + for (RefreshExclusion exclusion : exclusions) { + exclusion.persistData(resourceElement); + } + } + } + + /** + * @since 5.4 + */ + public synchronized void removeExclusion(IProject project, String configName, IResource resource, RefreshExclusion exclusion) { + + HashMap> resourceMap = getResourcesToExclusionsMap(project,configName); + List exclusions = resourceMap.get(resource); if (exclusions == null) { exclusions = new LinkedList(); - fResourceToExclusionsMap.put(resource, exclusions); + resourceMap.put(resource, exclusions); } exclusions.remove(exclusion); } - public synchronized void setExclusions(IResource resource, List newExclusions) { - getResourcesToExclusionsMap(); + /** + * @since 5.4 + */ + public synchronized void setExclusions(IProject project, String configName, IResource resource, List newExclusions) { + HashMap> resourceMap = getResourcesToExclusionsMap(project,configName); List exclusions = new LinkedList(newExclusions); - fResourceToExclusionsMap.put(resource, exclusions); + resourceMap.put(resource, exclusions); } - public synchronized void setResourcesToRefresh(IProject project, List resources) { - getProjectToResourcesMap(); - LinkedHashSet resourceSet = new LinkedHashSet(resources); - - fProjectToResourcesMap.put(project, resourceSet); + /** + * @since 5.4 + */ + public synchronized List getExclusions(IProject project, String configName, IResource resource) { + + HashMap> resourceMap = getResourcesToExclusionsMap(project, configName); + + List exclusions = resourceMap.get(resource); + if (exclusions == null) { + exclusions = new LinkedList(); + resourceMap.put(resource, exclusions); + } + + return exclusions; } - public synchronized boolean shouldResourceBeRefreshed(IResource resource) { + /** + * @since 5.4 + */ + public synchronized void setResourcesToExclusionsMap(IProject project, String configName, HashMap> source_resourceMap) { // List resources) { + + HashMap> target_resourceMap = getResourcesToExclusionsMap(project,configName); + target_resourceMap.clear(); + + Iterator resource_iterator = source_resourceMap.keySet().iterator(); + while (resource_iterator.hasNext()) { + IResource source_resource = resource_iterator.next(); + List source_exclusions = source_resourceMap.get(source_resource); + List target_exclusions = new LinkedList(); + for (RefreshExclusion exclusion : source_exclusions) { + target_exclusions.add(exclusion); + } + + // ADD the exclusion list for this resource + target_resourceMap.put(source_resource, target_exclusions); + } + } + + /** + * @since 5.4 + */ + public synchronized boolean shouldResourceBeRefreshed(String configName, IResource resource) { IProject project = resource.getProject(); - List resourcesToRefresh = getResourcesToRefresh(project); + List resourcesToRefresh = getResourcesToRefresh(project,configName); boolean isInSomeTree = false; IResource topLevelResource = null; @@ -666,7 +755,7 @@ public class RefreshScopeManager { // get any exclusions boolean isExcluded = false; - for (RefreshExclusion exclusion : getExclusions(topLevelResource)) { + for (RefreshExclusion exclusion : getExclusions(project, configName, topLevelResource)) { if (exclusion.testExclusionChain(resource)) { isExcluded = true; break; @@ -674,7 +763,5 @@ public class RefreshScopeManager { } return !isExcluded; - } - } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/resources/ResourceExclusion.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/resources/ResourceExclusion.java index 6b3ec75955a..b2e1503a2d7 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/resources/ResourceExclusion.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/resources/ResourceExclusion.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 IBM Corporation and others. + * Copyright (c) 2011, 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 @@ -81,4 +81,13 @@ public class ResourceExclusion extends RefreshExclusion { return false; } + @Override + public Object clone() { + ResourceExclusion clone = new ResourceExclusion(); + + copyTo(clone); + + return clone; + } + } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionRefactoringTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionRefactoringTest.java index e7d2716525f..471a174916f 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionRefactoringTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionRefactoringTest.java @@ -1737,6 +1737,103 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { assertRefactoringSuccess(); } + //test.c + //void test() { + // int i = 0; + // while (i <= 10) { + // /*$*/i++;/*$$*/ + // } + //} + //==================== + //int extracted(int i) { + // i++; + // return i; + //} + // + //void test() { + // int i = 0; + // while (i <= 10) { + // i = extracted(i); + // } + //} + public void testOutputParametersDetectionInWhileLoop() throws Exception { + assertRefactoringSuccess(); + } + + //test.c + //void test() { + // int i = 0; + //loop: + // if (i > 10) return; + // /*$*/i++;/*$$*/ + // goto loop; + //} + //==================== + //int extracted(int i) { + // i++; + // return i; + //} + // + //void test() { + // int i = 0; + //loop: + // if (i > 10) return; + // i = extracted(i); + // goto loop; + //} + public void testOutputParametersDetectionWithGotoLoopSimple() throws Exception { + assertRefactoringSuccess(); + } + + //test.c + //void test() { + // int a = 0, b = 0, c = 0, d = 0; + //loop1: + // if (a > 1) return; + // goto loop1; + //loop2: + // if (b > 2) return; + //loop3: + // if (c > 3) return; + // goto loop2; + //loop4: + // if (d > 4) return; + // goto loop3; + // /*$*/a++; + // b++; + // c++; + // d++;/*$$*/ + // goto loop4; + //} + //==================== + //int extracted(int a, int b, int* c, int* d) { + // a++; + // b++; + // *c++; + // *d++; + // return b; + //} + // + //void test() { + // int a = 0, b = 0, c = 0, d = 0; + //loop1: + // if (a > 1) return; + // goto loop1; + //loop2: + // if (b > 2) return; + //loop3: + // if (c > 3) return; + // goto loop2; + //loop4: + // if (d > 4) return; + // goto loop3; + // b = extracted(a, b, &c, &d); + // goto loop4; + //} + public void testOutputParametersDetectionWithGotoLoopComplex() throws Exception { + assertRefactoringSuccess(); + } + //main.cpp //void method() { // /*$*/for (int var = 0; var < 100; ++var) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/FlowAnalyzer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/FlowAnalyzer.java index 4fbf5a0dcb3..abb635e644b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/FlowAnalyzer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/FlowAnalyzer.java @@ -134,7 +134,7 @@ abstract class FlowAnalyzer extends ASTGenericVisitor { fFlowContext= context; } - protected abstract boolean createReturnFlowInfo(IASTReturnStatement node); + protected abstract boolean shouldCreateReturnFlowInfo(IASTReturnStatement node); protected abstract boolean traverseNode(IASTNode node); @@ -589,7 +589,7 @@ abstract class FlowAnalyzer extends ASTGenericVisitor { } public int leave(IASTGotoStatement node) { - // TODO(sprigogin): Implement goto support + setFlowInfo(node, createBranch(node.getName())); return PROCESS_SKIP; } @@ -602,9 +602,7 @@ abstract class FlowAnalyzer extends ASTGenericVisitor { } public int leave(IASTLabelStatement node) { - FlowInfo info= assignFlowInfo(node, node.getNestedStatement()); - if (info != null) - info.removeLabel(node.getName()); + assignFlowInfo(node, node.getNestedStatement()); return PROCESS_SKIP; } @@ -639,7 +637,7 @@ abstract class FlowAnalyzer extends ASTGenericVisitor { } public int leave(IASTReturnStatement node) { - if (createReturnFlowInfo(node)) { + if (shouldCreateReturnFlowInfo(node)) { ReturnFlowInfo info= createReturn(node); setFlowInfo(node, info); info.merge(getFlowInfo(node.getReturnArgument()), fFlowContext); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/InOutFlowAnalyzer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/InOutFlowAnalyzer.java index 42a353bf092..b72d6841cdf 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/InOutFlowAnalyzer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/InOutFlowAnalyzer.java @@ -58,7 +58,7 @@ public class InOutFlowAnalyzer extends FlowAnalyzer { } @Override - protected boolean createReturnFlowInfo(IASTReturnStatement node) { + protected boolean shouldCreateReturnFlowInfo(IASTReturnStatement node) { // We are only traversing selected nodes. return true; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/InputFlowAnalyzer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/InputFlowAnalyzer.java index 162a85aa819..f2726269bf9 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/InputFlowAnalyzer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/refactoring/code/flow/InputFlowAnalyzer.java @@ -19,31 +19,38 @@ package org.eclipse.cdt.internal.corext.refactoring.code.flow; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.text.IRegion; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; import org.eclipse.cdt.core.dom.ast.IASTDoStatement; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTForStatement; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTGotoStatement; import org.eclipse.cdt.core.dom.ast.IASTIfStatement; +import org.eclipse.cdt.core.dom.ast.IASTLabelStatement; +import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTReturnStatement; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement; import org.eclipse.cdt.core.dom.ast.IASTWhileStatement; +import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement; +import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.corext.util.ASTNodes; public class InputFlowAnalyzer extends FlowAnalyzer { private static class LoopReentranceVisitor extends FlowAnalyzer { - private Selection fSelection; - private IASTNode fLoopNode; + private final Selection selection; + private final IASTNode loopNode; public LoopReentranceVisitor(FlowContext context, Selection selection, IASTNode loopNode) { super(context); - fSelection= selection; - fLoopNode= loopNode; + this.selection= selection; + this.loopNode= loopNode; } @Override @@ -52,13 +59,13 @@ public class InputFlowAnalyzer extends FlowAnalyzer { } @Override - protected boolean createReturnFlowInfo(IASTReturnStatement node) { + protected boolean shouldCreateReturnFlowInfo(IASTReturnStatement node) { // Make sure that the whole return statement is selected or located before the selection. - return ASTNodes.endOffset(node) <= fSelection.getEnd(); + return ASTNodes.endOffset(node) <= selection.getEnd(); } protected IASTNode getLoopNode() { - return fLoopNode; + return loopNode; } public void process(IASTNode node) { @@ -93,7 +100,7 @@ public class InputFlowAnalyzer extends FlowAnalyzer { setFlowInfo(node, forInfo); // If the for statement is the outermost loop then we only have to consider // the action. The parameter and expression are only evaluated once. - if (node == fLoopNode) { + if (node == loopNode) { forInfo.mergeAction(actionInfo, fFlowContext); } else { // Inner for loops are evaluated in the sequence expression, parameter, @@ -118,7 +125,7 @@ public class InputFlowAnalyzer extends FlowAnalyzer { setFlowInfo(node, forInfo); // The for statement is the outermost loop. In this case we only have // to consider the increment, condition and action. - if (node == fLoopNode) { + if (node == loopNode) { forInfo.mergeIncrement(incrementInfo, fFlowContext); forInfo.mergeCondition(conditionInfo, fFlowContext); forInfo.mergeAction(actionInfo, fFlowContext); @@ -141,9 +148,126 @@ public class InputFlowAnalyzer extends FlowAnalyzer { } } + private static class GotoLoopRegion implements IRegion { + final IASTLabelStatement firstLabelStatement; + IASTGotoStatement lastGotoStatement; + + GotoLoopRegion(IASTLabelStatement firstLabelStatement, IASTGotoStatement lastGotoStatement) { + this.firstLabelStatement = firstLabelStatement; + this.lastGotoStatement = lastGotoStatement; + } + + @Override + public int getOffset() { + return ASTNodes.offset(firstLabelStatement); + } + + @Override + public int getLength() { + return ASTNodes.endOffset(lastGotoStatement) - getOffset(); + } + } + + private static class GotoAnalyzer extends ASTVisitor { + private GotoLoopRegion[] gotoRegions = {}; + + public GotoAnalyzer() { + shouldVisitStatements = true; + } + + @Override + public int visit(IASTStatement node) { + if (!(node instanceof IASTLabelStatement)) + return PROCESS_CONTINUE; + + IASTLabelStatement labelStatement = (IASTLabelStatement) node; + IASTName labelName = ((IASTLabelStatement) node).getName(); + IBinding binding = labelName.resolveBinding(); + IASTName[] references = labelStatement.getTranslationUnit().getReferences(binding); + IASTGotoStatement lastGotoStatement = null; + for (IASTName name : references) { + if (name.getPropertyInParent() == IASTGotoStatement.NAME) { + IASTGotoStatement gotoStatement = (IASTGotoStatement) name.getParent(); + IASTStatement lastStatement = lastGotoStatement != null ? lastGotoStatement : labelStatement; + if (isBefore(lastStatement, gotoStatement)) { + lastGotoStatement = gotoStatement; + } + } + } + if (lastGotoStatement == null) + return PROCESS_CONTINUE; + + GotoLoopRegion newRegion = new GotoLoopRegion(labelStatement, lastGotoStatement); + boolean gaps = false; + for (int i = 0; i < gotoRegions.length; i++) { + GotoLoopRegion existing = gotoRegions[i]; + if (existing == null) + break; + if (isBefore(newRegion.firstLabelStatement, existing.lastGotoStatement)) { + if (isBefore(existing.lastGotoStatement, newRegion.lastGotoStatement)) { + existing.lastGotoStatement = newRegion.lastGotoStatement; + for (int j = i + 1; j < gotoRegions.length; j++) { + newRegion = gotoRegions[j]; + if (newRegion == null) + break; + if (isBefore(newRegion.firstLabelStatement, existing.lastGotoStatement)) { + if (isBefore(existing.lastGotoStatement, newRegion.lastGotoStatement)) { + existing.lastGotoStatement = newRegion.lastGotoStatement; + } + } + gotoRegions[j] = null; + gaps = true; + } + } + newRegion = null; + break; + } + } + if (gaps) { + ArrayUtil.compact(gotoRegions); + } else if (newRegion != null) { + gotoRegions = ArrayUtil.append(gotoRegions, newRegion); + } + return PROCESS_SKIP; + } + + public GotoLoopRegion[] getGotoRegions() { + return ArrayUtil.trim(gotoRegions); + } + } + + private static class GotoReentranceVisitor extends FlowAnalyzer { + private final Selection selection; + private final GotoLoopRegion loopRegion; + + public GotoReentranceVisitor(FlowContext context, Selection selection, GotoLoopRegion loopRegion) { + super(context); + this.selection= selection; + this.loopRegion = loopRegion; + } + + @Override + protected boolean traverseNode(IASTNode node) { + return !isBefore(node, loopRegion.firstLabelStatement) && + !isBefore(loopRegion.lastGotoStatement, node); + } + + @Override + protected boolean shouldCreateReturnFlowInfo(IASTReturnStatement node) { + // Make sure that the whole return statement is selected or located before the selection. + return ASTNodes.endOffset(node) <= selection.getEnd(); + } + + public FlowInfo process(IASTFunctionDefinition node) { + node.accept(this); + return getFlowInfo(node); + } + } + private Selection fSelection; private boolean fDoLoopReentrance; private LoopReentranceVisitor fLoopReentranceVisitor; + private GotoReentranceVisitor fGotoReentranceVisitor; public InputFlowAnalyzer(FlowContext context, Selection selection, boolean doLoopReentrance) { super(context); @@ -154,16 +278,34 @@ public class InputFlowAnalyzer extends FlowAnalyzer { public FlowInfo perform(IASTFunctionDefinition node) { node.accept(this); + if (fDoLoopReentrance) { + GotoAnalyzer gotoAnalyzer = new GotoAnalyzer(); + node.accept(gotoAnalyzer); + GotoLoopRegion[] gotoRegions = gotoAnalyzer.getGotoRegions(); + for (GotoLoopRegion loopRegion : gotoRegions) { + if (fSelection.coveredBy(loopRegion)) { + GenericSequentialFlowInfo info= createSequential(); + info.merge(getFlowInfo(node), fFlowContext); + fGotoReentranceVisitor = new GotoReentranceVisitor(fFlowContext, fSelection, loopRegion); + FlowInfo gotoInfo = fGotoReentranceVisitor.process(node); + info.merge(gotoInfo, fFlowContext); + setFlowInfo(node, info); + break; + } + } + } return getFlowInfo(node); } @Override protected boolean traverseNode(IASTNode node) { + if (node instanceof IASTLabelStatement) + return true; return ASTNodes.endOffset(node) > fSelection.getEnd(); } @Override - protected boolean createReturnFlowInfo(IASTReturnStatement node) { + protected boolean shouldCreateReturnFlowInfo(IASTReturnStatement node) { // Make sure that the whole return statement is located after the selection. // There can be cases like return i + [x + 10] * 10; In this case we must not create // a return info node. @@ -210,7 +352,7 @@ public class InputFlowAnalyzer extends FlowAnalyzer { (elsePart != null && fSelection.coveredBy(elsePart))) { GenericSequentialFlowInfo info= createSequential(); setFlowInfo(node, info); - endVisitConditional(info, node.getLogicalConditionExpression(), new IASTNode[] { thenPart, elsePart }); + leaveConditional(info, node.getLogicalConditionExpression(), new IASTNode[] { thenPart, elsePart }); return PROCESS_SKIP; } return super.leave(node); @@ -233,7 +375,7 @@ public class InputFlowAnalyzer extends FlowAnalyzer { (elsePart != null && fSelection.coveredBy(elsePart))) { GenericSequentialFlowInfo info= createSequential(); setFlowInfo(node, info); - endVisitConditional(info, node.getConditionExpression(), new IASTNode[] { thenPart, elsePart }); + leaveConditional(info, node.getConditionExpression(), new IASTNode[] { thenPart, elsePart }); return PROCESS_SKIP; } return super.leave(node); @@ -280,10 +422,9 @@ public class InputFlowAnalyzer extends FlowAnalyzer { return PROCESS_SKIP; } - private void endVisitConditional(GenericSequentialFlowInfo info, IASTNode condition, IASTNode[] branches) { + private void leaveConditional(GenericSequentialFlowInfo info, IASTNode condition, IASTNode[] branches) { info.merge(getFlowInfo(condition), fFlowContext); - for (int i= 0; i < branches.length; i++) { - IASTNode branch= branches[i]; + for (IASTNode branch : branches) { if (branch != null && fSelection.coveredBy(branch)) { info.merge(getFlowInfo(branch), fFlowContext); break; @@ -301,4 +442,8 @@ public class InputFlowAnalyzer extends FlowAnalyzer { info.merge(fLoopReentranceVisitor.getFlowInfo(node), fFlowContext); setFlowInfo(node, info); } + + private static boolean isBefore(IASTNode node1, IASTNode node2) { + return CPPSemantics.declaredBefore(node1, node2, false); + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreInfo.java new file mode 100644 index 00000000000..726a6fd47e6 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreInfo.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson 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: + * Marc Khouzam (Ericsson) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal; + +import org.eclipse.cdt.internal.core.ICoreInfo; + +public class CoreInfo implements ICoreInfo { + private String fId; + private String fPhysicalId; + + public CoreInfo(String id, String pId) { + fId = id; + fPhysicalId = pId; + } + + @Override + public String getId() { + return fId; + } + + @Override + public String getPhysicalId() { + return fPhysicalId; + } +} \ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreList.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreList.java index c8a70ec724e..55007d29bb0 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreList.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/CoreList.java @@ -24,29 +24,15 @@ import org.eclipse.cdt.internal.core.ICoreInfo; */ public class CoreList { - private class CoreInfo implements ICoreInfo { - private String fId; - private String fPhysicalId; - - public CoreInfo(String id, String pId) { - fId = id; - fPhysicalId = pId; - } - - @Override - public String getId() { - return fId; - } - - @Override - public String getPhysicalId() { - return fPhysicalId; - } - } - private ICoreInfo[] fCoreList; + private String fCoreFileName; public CoreList() { + fCoreFileName = "/proc/cpuinfo"; //$NON-NLS-1$ + } + + public CoreList(String fileName) { + fCoreFileName = fileName; } /** @@ -60,7 +46,7 @@ public class CoreList { return fCoreList; } - File cpuInfo = new File("/proc/cpuinfo"); //$NON-NLS-1$ + File cpuInfo = new File(fCoreFileName); Vector coreInfo = new Vector(); BufferedReader reader = null; diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/service/command/commands/MIMetaGetCPUInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/service/command/commands/MIMetaGetCPUInfo.java new file mode 100644 index 00000000000..0368945d9a7 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/service/command/commands/MIMetaGetCPUInfo.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson 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: + * Marc Khouzam (Ericsson) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.service.command.commands; + +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.service.command.ICommand; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext; +import org.eclipse.cdt.dsf.debug.service.command.ICommandResult; +import org.eclipse.cdt.dsf.gdb.internal.service.command.output.MIMetaGetCPUInfoInfo; + +/** + * Meta MI command to fetch CPU info from the target. + * @since 4.1 + */ +public class MIMetaGetCPUInfo implements ICommand { + + private final ICommandControlDMContext fCtx; + + public MIMetaGetCPUInfo(ICommandControlDMContext ctx) { + fCtx = ctx; + } + + @Override + public ICommand coalesceWith( ICommand command ) { + return null ; + } + + @Override + public IDMContext getContext(){ + return fCtx; + } + + @Override + public boolean equals(Object other) { + if (other == null) return false; + if (!(other.getClass().equals(getClass()))) return false; + + // Since other is the same class is this, we are sure it is of type MIMetaGetCPUInfo also + MIMetaGetCPUInfo otherCmd = (MIMetaGetCPUInfo)other; + return fCtx == null ? otherCmd.fCtx == null : fCtx.equals(otherCmd.fCtx); + } + + @Override + public int hashCode() { + return fCtx == null ? getClass().hashCode() : getClass().hashCode() ^ fCtx.hashCode(); + } + + @Override + public String toString() { + return getClass().getName() + (fCtx == null ? "null" : fCtx.toString()); //$NON-NLS-1$ + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/service/command/output/MIMetaGetCPUInfoInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/service/command/output/MIMetaGetCPUInfoInfo.java new file mode 100644 index 00000000000..49a301d12b4 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/service/command/output/MIMetaGetCPUInfoInfo.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson 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: + * Marc Khouzam (Ericsson) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.service.command.output; + +import org.eclipse.cdt.dsf.debug.service.command.ICommand; +import org.eclipse.cdt.dsf.debug.service.command.ICommandResult; +import org.eclipse.cdt.internal.core.ICoreInfo; + +/** + * Result obtined from MIMetaGetCPUInfo. + * @since 4.1 + */ +@SuppressWarnings("restriction") +public class MIMetaGetCPUInfoInfo implements ICommandResult { + + private final ICoreInfo[] fCoresInfo; + + public MIMetaGetCPUInfoInfo(ICoreInfo[] info) { + fCoresInfo = info; + } + + public ICoreInfo[] getInfo() { return fCoresInfo; } + + @Override + public V getSubsetResult(ICommand command) { + return null; + } + + @Override + public String toString() { + return getClass().getSimpleName() + " (" + getInfo() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + } +} \ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBHardware.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBHardware.java index 27dc7cf8390..48d0a69d9ce 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBHardware.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBHardware.java @@ -7,16 +7,22 @@ * * Contributors: * Marc Khouzam (Ericsson) - initial API and implementation + * Marc Khouzam (Ericsson) - Updated to use /proc/cpuinfo for remote targets (Bug 374024) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service; +import java.io.File; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Hashtable; +import java.util.List; import java.util.Set; import java.util.Vector; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; @@ -25,11 +31,23 @@ import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.datamodel.IDMData; import org.eclipse.cdt.dsf.debug.service.ICachingService; +import org.eclipse.cdt.dsf.debug.service.command.CommandCache; +import org.eclipse.cdt.dsf.debug.service.command.ICommand; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControl; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext; +import org.eclipse.cdt.dsf.debug.service.command.ICommandListener; +import org.eclipse.cdt.dsf.debug.service.command.ICommandResult; +import org.eclipse.cdt.dsf.debug.service.command.ICommandToken; +import org.eclipse.cdt.dsf.debug.service.command.IEventListener; +import org.eclipse.cdt.dsf.gdb.internal.CoreInfo; import org.eclipse.cdt.dsf.gdb.internal.CoreList; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.gdb.internal.service.command.commands.MIMetaGetCPUInfo; +import org.eclipse.cdt.dsf.gdb.internal.service.command.output.MIMetaGetCPUInfoInfo; import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; import org.eclipse.cdt.dsf.mi.service.IMICommandControl; import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo; import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo.IThreadGroupInfo; import org.eclipse.cdt.dsf.service.AbstractDsfService; @@ -138,11 +156,14 @@ public class GDBHardware extends AbstractDsfService implements IGDBHardware, ICa private IGDBControl fCommandControl; private IGDBBackend fBackend; private CommandFactory fCommandFactory; - - // The list of cores should not change, so we can store - // it once we figured it out. - private ICPUDMContext[] fCPUs; - private ICoreDMContext[] fCores; + + // A command cache to cache the data gotten from /proc/cpuinfo + // Because we obtain the data differently for a local target + // than a remote target, we can't buffer an actual MI command, + // so instead, we use a MetaMICommand to "fetch the cpu info" + // Since the CPU info does not change, this cache does not need + // to be cleared. + private CommandCache fFetchCPUInfoCache; // Track if the debug session has been fully initialized. // Until then, we may not be connected to the remote target @@ -179,13 +200,18 @@ public class GDBHardware extends AbstractDsfService implements IGDBHardware, ICa * initialization is done. */ private void doInitialize(RequestMonitor requestMonitor) { - fSessionInitializationComplete = false; - - fCommandControl = getServicesTracker().getService(IGDBControl.class); - fBackend = getServicesTracker().getService(IGDBBackend.class); - fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); + fCommandControl = getServicesTracker().getService(IGDBControl.class); + fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); + + fBackend = getServicesTracker().getService(IGDBBackend.class); + + // The cache does not go directly to the commandControl service. + // Instead is goes through a CPUInfoManager which will decide how to + // handle getting the required cpu info + fFetchCPUInfoCache = new CommandCache(getSession(), new CPUInfoManager()); + fFetchCPUInfoCache.setContextAvailable(fCommandControl.getContext(), true); getSession().addServiceEventListener(this, null); @@ -208,7 +234,7 @@ public class GDBHardware extends AbstractDsfService implements IGDBHardware, ICa @Override public void shutdown(RequestMonitor requestMonitor) { getSession().removeServiceEventListener(this); - + fFetchCPUInfoCache.reset(); unregister(); super.shutdown(requestMonitor); } @@ -226,42 +252,25 @@ public class GDBHardware extends AbstractDsfService implements IGDBHardware, ICa } @Override - public void getCPUs(IHardwareTargetDMContext dmc, DataRequestMonitor rm) { + public void getCPUs(final IHardwareTargetDMContext dmc, final DataRequestMonitor rm) { if (!fSessionInitializationComplete) { // We are not ready to answer yet rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Debug session not initialized yet", null)); //$NON-NLS-1$ return; } - if (fCPUs != null) { - rm.done(fCPUs); - return; - } - - if (fBackend.getSessionType() == SessionType.REMOTE) { - // Until we can get /proc/cpuinfo from the remote, we can't do anything - fCPUs = new ICPUDMContext[0]; - rm.done(fCPUs); + if (Platform.getOS().equals(Platform.OS_LINUX)) { + fFetchCPUInfoCache.execute( + new MIMetaGetCPUInfo(fCommandControl.getContext()), + new ImmediateDataRequestMonitor() { + @Override + protected void handleSuccess() { + rm.done(parseCoresInfoForCPUs(dmc, getData().getInfo())); + } + }); } else { - // For a local session, let's use /proc/cpuinfo on linux - if (Platform.getOS().equals(Platform.OS_LINUX)) { - Set cpuIds = new HashSet(); - - ICoreInfo[] cores = new CoreList().getCoreList(); - for (ICoreInfo core : cores) { - cpuIds.add(core.getPhysicalId()); - } - - String[] cpuIdsArray = cpuIds.toArray(new String[cpuIds.size()]); - fCPUs = new ICPUDMContext[cpuIdsArray.length]; - for (int i = 0; i < cpuIdsArray.length; i++) { - fCPUs[i] = createCPUContext(dmc, cpuIdsArray[i]); - } - } else { - // No way to know the CPUs on a local Windows session. - fCPUs = new ICPUDMContext[0]; - } - rm.done(fCPUs); + // No way to know the CPUs for Windows session. + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Operation not supported", null)); //$NON-NLS-1$ } } @@ -275,95 +284,61 @@ public class GDBHardware extends AbstractDsfService implements IGDBHardware, ICa if (dmc instanceof ICPUDMContext) { // Get the cores under this particular CPU - ICPUDMContext cpuDmc = (ICPUDMContext)dmc; + final ICPUDMContext cpuDmc = (ICPUDMContext)dmc; - if (fBackend.getSessionType() == SessionType.REMOTE) { - rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Operation not supported", null)); //$NON-NLS-1$ - } else { - if (Platform.getOS().equals(Platform.OS_LINUX)) { - // Use /proc/cpuinfo to find the cores and match them to the specified CPU - ICoreInfo[] cores = new CoreList().getCoreList(); - - Vector coreDmcs = new Vector(); - for (ICoreInfo core : cores) { - if (core.getPhysicalId().equals(cpuDmc.getId())){ - // This core belongs to the right CPU - coreDmcs.add(new GDBCoreDMC(getSession().getId(), cpuDmc, core.getId())); - } - } - - rm.done(coreDmcs.toArray(new ICoreDMContext[coreDmcs.size()])); - } else { - // No way to know the cores for a specific CPU on a remote Windows session. - rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Operation not supported", null)); //$NON-NLS-1$ - } - } - } else if (dmc instanceof IHardwareTargetDMContext) { - // Get all the cores for this target - - final IHardwareTargetDMContext targetDmc = (IHardwareTargetDMContext)dmc; - - // We already know the list of cores. Just return it. - if (fCores != null) { - rm.done(fCores); - return; - } - - if (fBackend.getSessionType() == SessionType.REMOTE) { - // For a remote session, we can use GDB's -list-thread-groups --available - // command, which shows on which cores a process is running. This does - // not necessarily give the exhaustive list of cores, but that is the best - // we have right now. - // - // In this case, we don't have knowledge about CPUs, so we lump all cores - // into a single CPU. - fCommandControl.queueCommand( - fCommandFactory.createMIListThreadGroups(fCommandControl.getContext(), true), - new DataRequestMonitor(ImmediateExecutor.getInstance(), rm) { + if (Platform.getOS().equals(Platform.OS_LINUX)) { + fFetchCPUInfoCache.execute( + new MIMetaGetCPUInfo(fCommandControl.getContext()), + new ImmediateDataRequestMonitor() { @Override protected void handleSuccess() { - // First extract the string id for every core GDB reports - Set coreIds = new HashSet(); - IThreadGroupInfo[] groups = getData().getGroupList(); - for (IThreadGroupInfo group : groups) { - coreIds.addAll(Arrays.asList(group.getCores())); - } - - // Now create the context for each distinct core - // - // We don't have CPU info in this case so let's put them all under - // a single CPU - ICPUDMContext cpuDmc = createCPUContext(targetDmc, "0"); //$NON-NLS-1$ - Set coreDmcs = new HashSet(); - for (String id : coreIds) { - coreDmcs.add(new GDBCoreDMC(getSession().getId(), cpuDmc, id)); - } - fCores = coreDmcs.toArray(new ICoreDMContext[coreDmcs.size()]); - - rm.done(fCores); + rm.done(parseCoresInfoForCores(cpuDmc, getData().getInfo())); } }); } else { - // For a local session, -list-thread-groups --available does not return - // the cores field. Let's use /proc/cpuinfo on linux instead - if (Platform.getOS().equals(Platform.OS_LINUX)) { - ICoreInfo[] cores = new CoreList().getCoreList(); - fCores = new ICoreDMContext[cores.length]; - for (int i = 0; i < cores.length; i++) { - ICPUDMContext cpuDmc = createCPUContext(targetDmc, cores[i].getPhysicalId()); - fCores[i] = createCoreContext(cpuDmc, cores[i].getId()); - } - } else { - // No way to know the cores on a local Windows session. - fCores = new ICoreDMContext[0]; - } - rm.done(fCores); + // No way to know the cores for Windows session. + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Operation not supported", null)); //$NON-NLS-1$ } } else { rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid DMC type", null)); //$NON-NLS-1$ } } + /** + * Parse the CoreInfo and create the CPU Contexts for the hardwareTarget context. + */ + private ICPUDMContext[] parseCoresInfoForCPUs(IHardwareTargetDMContext dmc, ICoreInfo[] coresInfo) { + Set cpuIds = new HashSet(); + ICPUDMContext[] CPUs; + + for (ICoreInfo core : coresInfo) { + cpuIds.add(core.getPhysicalId()); + } + + String[] cpuIdsArray = cpuIds.toArray(new String[cpuIds.size()]); + CPUs = new ICPUDMContext[cpuIdsArray.length]; + for (int i = 0; i < cpuIdsArray.length; i++) { + CPUs[i] = createCPUContext(dmc, cpuIdsArray[i]); + } + return CPUs; + } + + /** + * Parse the CoreInfo and create the Core Contexts for the specified CPU context. + */ + private ICoreDMContext[] parseCoresInfoForCores(ICPUDMContext cpuDmc, ICoreInfo[] coresInfo) { + + Vector coreDmcs = new Vector(); + for (ICoreInfo core : coresInfo) { + if (core.getPhysicalId().equals(cpuDmc.getId())){ + // This core belongs to the right CPU + coreDmcs.add(createCoreContext(cpuDmc, core.getId())); + } + } + + return coreDmcs.toArray(new ICoreDMContext[coreDmcs.size()]); + } + @Override public void getExecutionData(IDMContext dmc, DataRequestMonitor rm) { if (dmc instanceof ICoreDMContext) { @@ -397,7 +372,135 @@ public class GDBHardware extends AbstractDsfService implements IGDBHardware, ICa @Override public void flushCache(IDMContext context) { - fCPUs = null; - fCores = null; + // Although the CPUInfo does not change, + // this allows us to have a way to forcibly clear the cache. + // We would need to call this method from the UI somehow. + fFetchCPUInfoCache.reset(context); + } + + /** + * A commandControl that will decide what to do when needing to find the CPUInfo. + * The class is used together with a CommandCache an MIMetaCommands to fetch + * information we need. + */ + private class CPUInfoManager implements ICommandControl { + private final List fCommandProcessors = new ArrayList(); + + @Override + public ICommandToken queueCommand(final ICommand command, DataRequestMonitor rm) { + + final ICommandToken token = new ICommandToken() { + @Override + public ICommand getCommand() { + return command; + } + }; + + // The class does not buffer commands itself, but sends them directly to the real + // MICommandControl service. Therefore, we must immediately tell our calling cache that the command + // has been sent, since we can never cancel it. + processCommandSent(token); + + if (command instanceof MIMetaGetCPUInfo) { + @SuppressWarnings("unchecked") + final DataRequestMonitor drm = (DataRequestMonitor)rm; + final ICommandControlDMContext dmc = (ICommandControlDMContext)command.getContext(); + + if (fBackend.getSessionType() == SessionType.REMOTE) { + // Ask GDB to fetch /proc/cpuinfo from the remote target, and then we parse it. + String remoteFile = "/proc/cpuinfo"; //$NON-NLS-1$ + final String localFile = "/tmp/" + GdbPlugin.PLUGIN_ID + ".cpuinfo." + getSession().getId(); //$NON-NLS-1$ //$NON-NLS-2$ + fCommandControl.queueCommand( + fCommandFactory.createCLIRemoteGet(dmc, remoteFile, localFile), + new ImmediateDataRequestMonitor(rm) { + @Override + protected void handleSuccess() { + ICoreInfo[] info = new CoreList(localFile).getCoreList(); + // Now that we processed the file, remove it to avoid polluting the file system + new File(localFile).delete(); + drm.done(new MIMetaGetCPUInfoInfo(info)); + processCommandDone(token, drm.getData()); + } + @Override + protected void handleError() { + // On some older linux versions, gdbserver is not able to read from /proc + // because it is a pseudo filesystem. + // We need to find some other method of getting the info we need. + + // For a remote session, we can use GDB's -list-thread-groups --available + // command, which shows on which cores a process is running. This does + // not necessarily give the exhaustive list of cores, but that is the best + // we have in this case. + // + // In this case, we don't have knowledge about CPUs, so we lump all cores + // into a single CPU. + + fCommandControl.queueCommand( + fCommandFactory.createMIListThreadGroups(dmc, true), + new ImmediateDataRequestMonitor(drm) { + @Override + protected void handleSuccess() { + // First extract the string id for every core GDB reports + Set coreIds = new HashSet(); + IThreadGroupInfo[] groups = getData().getGroupList(); + for (IThreadGroupInfo group : groups) { + coreIds.addAll(Arrays.asList(group.getCores())); + } + + // Now create the context for each distinct core + // + // We don't have CPU info in this case so let's put them all under a single CPU + final String defaultCPUId = "0"; //$NON-NLS-1$ + ICoreInfo[] info = new ICoreInfo[coreIds.size()]; + int i = 0; + for (String id : coreIds) { + info[i++] = new CoreInfo(id, defaultCPUId); + } + drm.done(new MIMetaGetCPUInfoInfo(info)); + processCommandDone(token, drm.getData()); + } + }); + } + }); + } else { + // For a local session, parse /proc/cpuinfo directly. + ICoreInfo[] info = new CoreList("/proc/cpuinfo").getCoreList(); //$NON-NLS-1$ + drm.done(new MIMetaGetCPUInfoInfo(info)); + processCommandDone(token, drm.getData()); + } + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, + "Unexpected Meta command", null)); //$NON-NLS-1$ + rm.done(); + } + return token; + } + + // Need to support these as they are used by the commandCache + @Override + public void addCommandListener(ICommandListener processor) { fCommandProcessors.add(processor); } + @Override + public void removeCommandListener(ICommandListener processor) { fCommandProcessors.remove(processor); } + + + private void processCommandSent(ICommandToken token) { + for (ICommandListener processor : fCommandProcessors) { + processor.commandSent(token); + } + } + + private void processCommandDone(ICommandToken token, ICommandResult result) { + for (ICommandListener processor : fCommandProcessors) { + processor.commandDone(token, result); + } + } + + @Override + public void addEventListener(IEventListener processor) { assert false : "Not supported"; } //$NON-NLS-1$ + @Override + public void removeEventListener(IEventListener processor) { assert false : "Not supported"; } //$NON-NLS-1$ + @Override + public void removeCommand(ICommandToken token) { assert false : "Not supported"; } //$NON-NLS-1$ + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java index 2efab02fff1..11b0b02aa5c 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java @@ -13,6 +13,8 @@ * Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121) * Mikhail Khodjaiants (Mentor Graphics) - Refactor common code in GDBControl* classes (bug 372795) * Marc Khouzam (Ericsson) - Pass errorStream to startCommandProcessing() (Bug 350837) + * Mikhail Khodjaiants (Mentor Graphics) - Terminate should cancel the initialization sequence + * if it is still running (bug 373845) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service.command; @@ -63,6 +65,7 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; import org.eclipse.cdt.dsf.service.DsfSession; 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.Status; @@ -116,6 +119,8 @@ public class GDBControl extends AbstractMIControl implements IGDBControl { */ private final List fFeatures = new ArrayList(); + private Sequence fInitializationSequence; + private boolean fTerminated; /** @@ -191,7 +196,13 @@ public class GDBControl extends AbstractMIControl implements IGDBControl { return; } fTerminated = true; - + + // If the initialization sequence is still running mark it as cancelled, + // to avoid reporting errors to the user, since we are terminating anyway. + if (fInitializationSequence != null) { + fInitializationSequence.getRequestMonitor().cancel(); + } + // To fix bug 234467: // Interrupt GDB in case the inferior is running. // That way, the inferior will also be killed when we exit GDB. @@ -290,20 +301,23 @@ public class GDBControl extends AbstractMIControl implements IGDBControl { } catch (CoreException e) {} // We need a RequestMonitorWithProgress, if we don't have one, we create one. - RequestMonitorWithProgress progressRm; - if (rm instanceof RequestMonitorWithProgress) { - progressRm = (RequestMonitorWithProgress)rm; - } else { - progressRm = new RequestMonitorWithProgress(getExecutor(), new NullProgressMonitor()) { - @Override - protected void handleCompleted() { - rm.setStatus(getStatus()); - rm.done(); - } - }; - } + IProgressMonitor monitor = (rm instanceof RequestMonitorWithProgress) ? + ((RequestMonitorWithProgress)rm).getProgressMonitor() : new NullProgressMonitor(); + RequestMonitorWithProgress progressRm = new RequestMonitorWithProgress(getExecutor(), monitor) { - ImmediateExecutor.getInstance().execute(getCompleteInitializationSequence(attributes, progressRm)); + @Override + protected void handleCompleted() { + fInitializationSequence = null; + if (!isCanceled()) { + // Only set the status if the user has not cancelled the operation already. + rm.setStatus(getStatus()); + } + rm.done(); + } + }; + + fInitializationSequence = getCompleteInitializationSequence(attributes, progressRm); + ImmediateExecutor.getInstance().execute(fInitializationSequence); } /** diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java index d2c23d0a0c9..c31feea345f 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java @@ -47,6 +47,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.CLIJump; import org.eclipse.cdt.dsf.mi.service.command.commands.CLIMaintenance; import org.eclipse.cdt.dsf.mi.service.command.commands.CLIPasscount; import org.eclipse.cdt.dsf.mi.service.command.commands.CLIRecord; +import org.eclipse.cdt.dsf.mi.service.command.commands.CLIRemoteGet; import org.eclipse.cdt.dsf.mi.service.command.commands.CLISource; import org.eclipse.cdt.dsf.mi.service.command.commands.CLIThread; import org.eclipse.cdt.dsf.mi.service.command.commands.CLITrace; @@ -266,6 +267,11 @@ public class CommandFactory { return new CLIRecord(ctx, enable); } + /** @since 4.1 */ + public ICommand createCLIRemoteGet(ICommandControlDMContext ctx, String remoteFile, String localFile) { + return new CLIRemoteGet(ctx, remoteFile, localFile); + } + public ICommand createCLISource(ICommandControlDMContext ctx, String file) { return new CLISource(ctx, file); } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIRemote.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIRemote.java new file mode 100644 index 00000000000..75ea5084d58 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIRemote.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson 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: + * Marc Khouzam (Ericsson) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; + +/** + * Base class for the 'remote' command of GDB. + * + * @since 4.1 + */ +public class CLIRemote extends CLICommand +{ + public CLIRemote(IDMContext ctx, String[] params) { + super(ctx, "remote"); //$NON-NLS-1$ + setParameters(params); + } +} \ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIRemoteGet.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIRemoteGet.java new file mode 100644 index 00000000000..3ace4ecee3b --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIRemoteGet.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2012 Ericsson 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: + * Marc Khouzam (Ericsson) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext; + +/** + * remote get targetfile hostfile + * Copy file targetfile from the target system to hostfile on the host system. + * @since 4.1 + */ +public class CLIRemoteGet extends CLIRemote +{ + public CLIRemoteGet(ICommandControlDMContext ctx, String targetfile, String hostfile) { + super(ctx, new String[] { "get", targetfile, hostfile }); //$NON-NLS-1$ + } +} \ No newline at end of file