mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Merge remote-tracking branch 'cdt/master' into sd90
This commit is contained in:
commit
c6a26fb0b1
326 changed files with 20066 additions and 1046 deletions
|
@ -7,15 +7,13 @@ Bundle-Activator: org.eclipse.cdt.codan.core.cxx.Activator
|
||||||
Require-Bundle: org.eclipse.core.runtime,
|
Require-Bundle: org.eclipse.core.runtime,
|
||||||
org.eclipse.cdt.core,
|
org.eclipse.cdt.core,
|
||||||
org.eclipse.cdt.codan.core,
|
org.eclipse.cdt.codan.core,
|
||||||
org.eclipse.core.resources
|
org.eclipse.core.resources,
|
||||||
|
org.eclipse.core.filesystem
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Export-Package: org.eclipse.cdt.codan.core.cxx,
|
Export-Package: org.eclipse.cdt.codan.core.cxx,
|
||||||
org.eclipse.cdt.codan.core.cxx.internal.model;
|
org.eclipse.cdt.codan.core.cxx.externaltool,
|
||||||
x-friends:="org.eclipse.cdt.codan.checkers.ui,
|
org.eclipse.cdt.codan.core.cxx.internal.model;x-friends:="org.eclipse.cdt.codan.checkers.ui,org.eclipse.cdt.codan.ui,org.eclipse.cdt.codan.ui.cxx",
|
||||||
org.eclipse.cdt.codan.ui,
|
org.eclipse.cdt.codan.core.cxx.internal.model.cfg;x-friends:="org.eclipse.cdt.codan.core.test",
|
||||||
org.eclipse.cdt.codan.ui.cxx",
|
|
||||||
org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
|
|
||||||
x-friends:="org.eclipse.cdt.codan.core.test",
|
|
||||||
org.eclipse.cdt.codan.core.cxx.model
|
org.eclipse.cdt.codan.core.cxx.model
|
||||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||||
Bundle-Vendor: %Bundle-Vendor
|
Bundle-Vendor: %Bundle-Vendor
|
||||||
|
|
|
@ -74,13 +74,13 @@ public class Activator extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs an internal error with the specified throwable
|
* Logs an internal error with the specified {@code Throwable}.
|
||||||
*
|
*
|
||||||
* @param e
|
* @param t
|
||||||
* the exception to be logged
|
* the {@code Throwable} to be logged
|
||||||
*/
|
*/
|
||||||
public static void log(Throwable e) {
|
public static void log(Throwable t) {
|
||||||
log(new Status(IStatus.ERROR, PLUGIN_ID, 1, "Internal Error", e)); //$NON-NLS-1$
|
log(new Status(IStatus.ERROR, PLUGIN_ID, 1, "Internal Error", t)); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,4 +92,18 @@ public class Activator extends Plugin {
|
||||||
public static void log(String message) {
|
public static void log(String message) {
|
||||||
log(new Status(IStatus.ERROR, PLUGIN_ID, 1, message, null));
|
log(new Status(IStatus.ERROR, PLUGIN_ID, 1, message, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs an internal error with the specified message and {@code Throwable}.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* the error message to log
|
||||||
|
* @param t
|
||||||
|
* the {@code Throwable} to be logged
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public static void log(String message, Throwable t) {
|
||||||
|
log(new Status(IStatus.ERROR, PLUGIN_ID, 1, message, t));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -406,6 +406,14 @@ public final class CxxAstUtils {
|
||||||
if (!(expression instanceof IASTFunctionCallExpression))
|
if (!(expression instanceof IASTFunctionCallExpression))
|
||||||
return false;
|
return false;
|
||||||
IASTExpression functionNameExpression = ((IASTFunctionCallExpression) expression).getFunctionNameExpression();
|
IASTExpression functionNameExpression = ((IASTFunctionCallExpression) expression).getFunctionNameExpression();
|
||||||
|
if (functionNameExpression instanceof IASTIdExpression) {
|
||||||
|
IASTName name = ((IASTIdExpression)functionNameExpression).getName();
|
||||||
|
|
||||||
|
IBinding binding = name.resolveBinding();
|
||||||
|
if (binding!=null && binding instanceof IFunction && ((IFunction)binding).isNoReturn()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return functionNameExpression.getRawSignature().equals("exit"); //$NON-NLS-1$
|
return functionNameExpression.getRawSignature().equals("exit"); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,214 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.externaltool;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.core.ErrorParserContext.CODAN;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.CodanRuntime;
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.Activator;
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.internal.externaltool.ExternalToolInvoker;
|
||||||
|
import org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences;
|
||||||
|
import org.eclipse.cdt.codan.core.model.CheckerLaunchMode;
|
||||||
|
import org.eclipse.cdt.codan.core.model.IProblem;
|
||||||
|
import org.eclipse.cdt.codan.core.model.IProblemLocation;
|
||||||
|
import org.eclipse.cdt.codan.core.model.IProblemLocationFactory;
|
||||||
|
import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
|
||||||
|
import org.eclipse.cdt.codan.core.param.IProblemPreference;
|
||||||
|
import org.eclipse.cdt.codan.core.param.MapProblemPreference;
|
||||||
|
import org.eclipse.cdt.codan.core.param.RootProblemPreference;
|
||||||
|
import org.eclipse.cdt.codan.core.param.SharedRootProblemPreference;
|
||||||
|
import org.eclipse.cdt.core.ErrorParserManager;
|
||||||
|
import org.eclipse.cdt.core.IConsoleParser;
|
||||||
|
import org.eclipse.cdt.core.IMarkerGenerator;
|
||||||
|
import org.eclipse.cdt.core.ProblemMarkerInfo;
|
||||||
|
import org.eclipse.core.filesystem.URIUtil;
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for checkers that invoke external command-line tools to perform code checking.
|
||||||
|
* <p>
|
||||||
|
* A file, to be processed by this type of checker, must:
|
||||||
|
* <ol>
|
||||||
|
* <li>be in the current active editor</li>
|
||||||
|
* <li>not have any unsaved changes</li>
|
||||||
|
* </ol>
|
||||||
|
* </p>
|
||||||
|
* By default, implementations of this checker are not allowed to run while the user types, since
|
||||||
|
* external tools cannot see unsaved changes.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWithProblemPreferences
|
||||||
|
implements IMarkerGenerator {
|
||||||
|
private final IInvocationParametersProvider parametersProvider;
|
||||||
|
private final ArgsSeparator argsSeparator;
|
||||||
|
private final ConfigurationSettings settings;
|
||||||
|
private final ExternalToolInvoker externalToolInvoker;
|
||||||
|
private final RootProblemPreference preferences;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param settings user-configurable external tool configuration settings.
|
||||||
|
*/
|
||||||
|
public AbstractExternalToolBasedChecker(ConfigurationSettings settings) {
|
||||||
|
this(new InvocationParametersProvider(), new ArgsSeparator(), settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param parametersProvider provides the parameters to pass when invoking the external tool.
|
||||||
|
* @param argsSeparator separates the arguments to pass to the external tool executable. These
|
||||||
|
* arguments are stored in a single {@code String}.
|
||||||
|
* @param settings user-configurable external tool configuration settings.
|
||||||
|
*/
|
||||||
|
public AbstractExternalToolBasedChecker(IInvocationParametersProvider parametersProvider,
|
||||||
|
ArgsSeparator argsSeparator, ConfigurationSettings settings) {
|
||||||
|
this.parametersProvider = parametersProvider;
|
||||||
|
this.argsSeparator = argsSeparator;
|
||||||
|
this.settings = settings;
|
||||||
|
externalToolInvoker = new ExternalToolInvoker();
|
||||||
|
preferences = new SharedRootProblemPreference();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code false} because this checker cannot run "as you type" by default.
|
||||||
|
* @return {@code false}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean runInEditor() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean processResource(IResource resource) {
|
||||||
|
process(resource);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void process(IResource resource) {
|
||||||
|
try {
|
||||||
|
InvocationParameters parameters = parametersProvider.createParameters(resource);
|
||||||
|
if (parameters != null) {
|
||||||
|
invokeExternalTool(parameters);
|
||||||
|
}
|
||||||
|
} catch (Throwable error) {
|
||||||
|
logResourceProcessingFailure(error, resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void invokeExternalTool(InvocationParameters parameters) throws Throwable {
|
||||||
|
updateConfigurationSettingsFromPreferences(parameters.getActualFile());
|
||||||
|
IConsoleParser[] parsers = new IConsoleParser[] { createErrorParserManager(parameters) };
|
||||||
|
try {
|
||||||
|
externalToolInvoker.invoke(parameters, settings, argsSeparator, parsers);
|
||||||
|
} catch (InvocationFailure error) {
|
||||||
|
handleInvocationFailure(error, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateConfigurationSettingsFromPreferences(IResource fileToProcess) {
|
||||||
|
IProblem problem = getProblemById(getReferenceProblemId(), fileToProcess);
|
||||||
|
MapProblemPreference preferences = (MapProblemPreference) problem.getPreference();
|
||||||
|
settings.updateValuesFrom(preferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ErrorParserManager createErrorParserManager(InvocationParameters parameters) {
|
||||||
|
IProject project = parameters.getActualFile().getProject();
|
||||||
|
URI workingDirectory = URIUtil.toURI(parameters.getWorkingDirectory());
|
||||||
|
return new ErrorParserManager(project, workingDirectory, this, getParserIDs(), CODAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the IDs of the parsers to use to parse the output of the external tool.
|
||||||
|
*/
|
||||||
|
protected abstract String[] getParserIDs();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a failure reported when invoking the external tool. This implementation simply
|
||||||
|
* logs the failure.
|
||||||
|
* @param error the reported failure.
|
||||||
|
* @param parameters the parameters passed to the external tool executable.
|
||||||
|
*/
|
||||||
|
protected void handleInvocationFailure(InvocationFailure error, InvocationParameters parameters) {
|
||||||
|
logResourceProcessingFailure(error, parameters.getActualFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logResourceProcessingFailure(Throwable error, IResource resource) {
|
||||||
|
String location = resource.getLocation().toOSString();
|
||||||
|
String msg = String.format("Unable to process resource %s", location); //$NON-NLS-1$
|
||||||
|
Activator.log(msg, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id of the problem used as reference to obtain this checker's preferences. All
|
||||||
|
* preferences in a external-tool-based checker are shared among its defined problems.
|
||||||
|
* @return the id of the problem used as reference to obtain this checker's preferences.
|
||||||
|
*/
|
||||||
|
protected abstract String getReferenceProblemId();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initPreferences(IProblemWorkingCopy problem) {
|
||||||
|
super.initPreferences(problem);
|
||||||
|
getLaunchModePreference(problem).enableInLaunchModes(
|
||||||
|
CheckerLaunchMode.RUN_ON_FULL_BUILD,
|
||||||
|
CheckerLaunchMode.RUN_ON_INC_BUILD,
|
||||||
|
CheckerLaunchMode.RUN_ON_FILE_SAVE,
|
||||||
|
CheckerLaunchMode.RUN_ON_DEMAND);
|
||||||
|
addPreference(problem, settings.getPath());
|
||||||
|
addPreference(problem, settings.getArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addPreference(IProblemWorkingCopy problem, SingleConfigurationSetting<?> setting) {
|
||||||
|
IProblemPreference descriptor = (IProblemPreference) setting.getDescriptor();
|
||||||
|
addPreference(problem, descriptor, setting.getDefaultValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setDefaultPreferenceValue(IProblemWorkingCopy problem, String key,
|
||||||
|
Object defaultValue) {
|
||||||
|
MapProblemPreference map = getTopLevelPreference(problem);
|
||||||
|
map.setChildValue(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RootProblemPreference getTopLevelPreference(IProblem problem) {
|
||||||
|
RootProblemPreference map = (RootProblemPreference) problem.getPreference();
|
||||||
|
if (map == null) {
|
||||||
|
map = preferences;
|
||||||
|
if (problem instanceof IProblemWorkingCopy) {
|
||||||
|
((IProblemWorkingCopy) problem).setPreference(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
@Override
|
||||||
|
public void addMarker(IResource file, int lineNumber, String description, int severity,
|
||||||
|
String variableName) {
|
||||||
|
addMarker(new ProblemMarkerInfo(file, lineNumber, description, severity, variableName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addMarker(ProblemMarkerInfo info) {
|
||||||
|
reportProblem(getReferenceProblemId(), createProblemLocation(info), info.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IProblemLocation createProblemLocation(ProblemMarkerInfo info) {
|
||||||
|
IProblemLocationFactory factory = CodanRuntime.getInstance().getProblemLocationFactory();
|
||||||
|
return factory.createProblemLocation(
|
||||||
|
(IFile) info.file, info.startChar, info.endChar, info.lineNumber);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.externaltool;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
// import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Separates the arguments, stored as a single {@code String}, to pass to an external tool. It uses
|
||||||
|
* an empty space as the delimiter and supports quoted arguments.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public class ArgsSeparator {
|
||||||
|
private static final char BACKSLASH = '\\';
|
||||||
|
private static final char DOUBLE_QUOTE = '"';
|
||||||
|
private static final char SINGLE_QUOTE = '\'';
|
||||||
|
private static final char SPACE = ' ';
|
||||||
|
|
||||||
|
private static final String[] NO_ARGS = {};
|
||||||
|
|
||||||
|
public String[] splitArguments(String s) {
|
||||||
|
if (s == null || s.isEmpty()) {
|
||||||
|
return NO_ARGS;
|
||||||
|
}
|
||||||
|
ParserState state = ParserState.NORMAL;
|
||||||
|
StringBuilder current = new StringBuilder();
|
||||||
|
List<String> args = new ArrayList<String>();
|
||||||
|
boolean lastTokenInQuotes = false;
|
||||||
|
char previous = 0;
|
||||||
|
for (char c : s.toCharArray()) {
|
||||||
|
switch (state) {
|
||||||
|
case IN_SINGLE_QUOTE:
|
||||||
|
if (previous != BACKSLASH && c == SINGLE_QUOTE) {
|
||||||
|
lastTokenInQuotes = true;
|
||||||
|
state = ParserState.NORMAL;
|
||||||
|
} else {
|
||||||
|
previous = c;
|
||||||
|
current.append(c);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IN_DOUBLE_QUOTE:
|
||||||
|
if (previous != BACKSLASH && c == DOUBLE_QUOTE) {
|
||||||
|
lastTokenInQuotes = true;
|
||||||
|
state = ParserState.NORMAL;
|
||||||
|
} else {
|
||||||
|
previous = c;
|
||||||
|
current.append(c);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
switch (c) {
|
||||||
|
case SINGLE_QUOTE:
|
||||||
|
if (previous != BACKSLASH) {
|
||||||
|
state = ParserState.IN_SINGLE_QUOTE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DOUBLE_QUOTE:
|
||||||
|
if (previous != BACKSLASH) {
|
||||||
|
state = ParserState.IN_DOUBLE_QUOTE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPACE:
|
||||||
|
if (lastTokenInQuotes || current.length() != 0) {
|
||||||
|
args.add(current.toString());
|
||||||
|
current.setLength(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
previous = c;
|
||||||
|
current.append(c);
|
||||||
|
}
|
||||||
|
lastTokenInQuotes = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lastTokenInQuotes || current.length() != 0) {
|
||||||
|
args.add(current.toString());
|
||||||
|
}
|
||||||
|
if (state != ParserState.NORMAL) {
|
||||||
|
throw new IllegalArgumentException("Unbalanced quotes in " + s); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
return args.toArray(new String[args.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static enum ParserState {
|
||||||
|
NORMAL, IN_SINGLE_QUOTE, IN_DOUBLE_QUOTE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.externaltool;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.internal.externaltool.ArgsSetting;
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.internal.externaltool.PathSetting;
|
||||||
|
import org.eclipse.cdt.codan.core.param.MapProblemPreference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User-configurable external tool settings.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public final class ConfigurationSettings {
|
||||||
|
private final PathSetting path;
|
||||||
|
private final ArgsSetting args;
|
||||||
|
private final String externalToolName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param externalToolName the name of the external tool. The name of the external tool is
|
||||||
|
* used in the labels of the settings' input fields. For example, assuming that the external
|
||||||
|
* tool's name is "Cppcheck", the input field for entering the path of the executable
|
||||||
|
* will have the label "Cppcheck Path".
|
||||||
|
* @param defaultPath the default path of the external tool.
|
||||||
|
* @param defaultArgs the default arguments to pass when invoking the external tool.
|
||||||
|
*/
|
||||||
|
public ConfigurationSettings(String externalToolName, File defaultPath, String defaultArgs) {
|
||||||
|
this.externalToolName = externalToolName;
|
||||||
|
this.path = new PathSetting(externalToolName, defaultPath);
|
||||||
|
this.args = new ArgsSetting(externalToolName, defaultArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the external tool, to be displayed to the user.
|
||||||
|
* @return the name of the external tool, to be displayed to the user.
|
||||||
|
*/
|
||||||
|
public String getExternalToolName() {
|
||||||
|
return externalToolName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the setting that specifies the path and name of the external tool to invoke.
|
||||||
|
* @return the setting that specifies the path and name of the external tool to invoke.
|
||||||
|
*/
|
||||||
|
public SingleConfigurationSetting<File> getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the setting that specifies the arguments to pass when invoking the external tool.
|
||||||
|
* @return the setting that specifies the arguments to pass when invoking the external tool.
|
||||||
|
*/
|
||||||
|
public SingleConfigurationSetting<String> getArgs() {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the values of the configuration settings value with the ones stored in the given
|
||||||
|
* preference map.
|
||||||
|
* @param preferences the given preference map that may contain the values to set.
|
||||||
|
* @throws ClassCastException if any of the values to set is not of the same type as the one
|
||||||
|
* supported by a setting.
|
||||||
|
*/
|
||||||
|
public void updateValuesFrom(MapProblemPreference preferences) {
|
||||||
|
path.updateValue(preferences);
|
||||||
|
args.updateValue(preferences);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.externaltool;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the parameters to pass when invoking an external tool.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public interface IInvocationParametersProvider {
|
||||||
|
/**
|
||||||
|
* Creates the parameters to pass when invoking an external tool.
|
||||||
|
* @param fileToProcess the file to process.
|
||||||
|
* @return the created parameters.
|
||||||
|
* @throws Throwable if something goes wrong.
|
||||||
|
*/
|
||||||
|
InvocationParameters createParameters(IResource fileToProcess) throws Throwable;
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.externaltool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that invocation of an external tool failed.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public class InvocationFailure extends Exception {
|
||||||
|
private static final long serialVersionUID = 6727101323050538885L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param message the detail message.
|
||||||
|
*/
|
||||||
|
public InvocationFailure(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param message the detail message.
|
||||||
|
* @param cause the cause (which is saved for later retrieval by
|
||||||
|
* the <code>{@link #getCause()}</code> method.)
|
||||||
|
*/
|
||||||
|
public InvocationFailure(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.externaltool;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters to pass when invoking an external tool.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public final class InvocationParameters {
|
||||||
|
private final IResource originalFile;
|
||||||
|
private final IResource actualFile;
|
||||||
|
private final String actualFilePath;
|
||||||
|
private final IPath workingDirectory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param originalFile the original file to process.
|
||||||
|
* @param actualFile the actual file to process.
|
||||||
|
* @param actualFilePath the path of {@code actual}, in a format that the external tool can
|
||||||
|
* understand.
|
||||||
|
* @param workingDirectory the directory where the external tool should be executed.
|
||||||
|
* @see #getOriginalFile()
|
||||||
|
* @see #getActualFile()
|
||||||
|
*/
|
||||||
|
public InvocationParameters(IResource originalFile, IResource actualFile, String actualFilePath,
|
||||||
|
IPath workingDirectory) {
|
||||||
|
this.originalFile = originalFile;
|
||||||
|
this.actualFile = actualFile;
|
||||||
|
this.actualFilePath = actualFilePath;
|
||||||
|
this.workingDirectory = workingDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the original file to process. This is the file that triggered execution of
|
||||||
|
* a command-line tool when saved.
|
||||||
|
* @return the original file to process.
|
||||||
|
*/
|
||||||
|
public IResource getOriginalFile() {
|
||||||
|
return originalFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the actual file to process. It may not be the same as
|
||||||
|
* <code>{@link #getOriginalFile()}</code>, depending on how the external tool works.
|
||||||
|
* <p>
|
||||||
|
* A good example is an external tool that can only process C++ source files but not header
|
||||||
|
* files. If the <em>original</em> file is a header file, the checker could potentially find
|
||||||
|
* a C++ file that includes such header and use it as the <em>actual</em> file to process.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* We still need to keep a reference to the <em>actual</em> file, in order to add markers to
|
||||||
|
* the editor in case of problems found.
|
||||||
|
* </p>
|
||||||
|
* @return the actual file to process.
|
||||||
|
*/
|
||||||
|
public IResource getActualFile() {
|
||||||
|
return actualFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the path of <code>{@link #getActualFile()}</code>, in a format the external tool can
|
||||||
|
* understand.
|
||||||
|
* @return the path of the <em>actual</em> file to process.
|
||||||
|
*/
|
||||||
|
public String getActualFilePath() {
|
||||||
|
return actualFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the directory where the external tool should be executed.
|
||||||
|
* @return the directory where the external tool should be executed.
|
||||||
|
*/
|
||||||
|
public IPath getWorkingDirectory() {
|
||||||
|
return workingDirectory;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.externaltool;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of <code>{@link InvocationParameters}</code>
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public class InvocationParametersProvider implements IInvocationParametersProvider {
|
||||||
|
/**
|
||||||
|
* Creates the parameters to pass when invoking an external tool.
|
||||||
|
* <p>
|
||||||
|
* In this implementation:
|
||||||
|
* <ul>
|
||||||
|
* <li>the <em>actual</em> file to process is the same as the <em>original</em> file</li>
|
||||||
|
* <li>the path of the actual file is its absolute path in the file system</li>
|
||||||
|
* <li>the working directory is {@code null}</li>
|
||||||
|
* </ul>
|
||||||
|
* @param fileToProcess the file to process.
|
||||||
|
* @return the created parameters.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public InvocationParameters createParameters(IResource fileToProcess) {
|
||||||
|
String path = fileToProcess.getLocation().toOSString();
|
||||||
|
return new InvocationParameters(fileToProcess, fileToProcess, path, null);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.externaltool;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.param.IProblemPreference;
|
||||||
|
import org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor;
|
||||||
|
import org.eclipse.cdt.codan.core.param.MapProblemPreference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single external tool configuration setting.
|
||||||
|
* @param <T> the type of the value this setting stores.
|
||||||
|
*
|
||||||
|
* @noextend This class is not intended to be extended by clients.
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public class SingleConfigurationSetting<T> {
|
||||||
|
private final IProblemPreferenceDescriptor descriptor;
|
||||||
|
private final T defaultValue;
|
||||||
|
private final Class<T> valueType;
|
||||||
|
|
||||||
|
private T value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param descriptor meta-data that tells the UI how to display this setting.
|
||||||
|
* @param defaultValue the setting's default value.
|
||||||
|
* @param valueType the type of the value to store (used for safe casting.)
|
||||||
|
*/
|
||||||
|
public SingleConfigurationSetting(IProblemPreferenceDescriptor descriptor, T defaultValue,
|
||||||
|
Class<T> valueType) {
|
||||||
|
this.descriptor = descriptor;
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
this.valueType = valueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns this setting's value.
|
||||||
|
* @return this setting's value.
|
||||||
|
*/
|
||||||
|
public T getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the meta-data that tells the UI how to display this setting.
|
||||||
|
* @return the meta-data that tells the UI how to display this setting.
|
||||||
|
*/
|
||||||
|
public IProblemPreferenceDescriptor getDescriptor() {
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns this setting's default value.
|
||||||
|
* @return this setting's default value.
|
||||||
|
*/
|
||||||
|
public T getDefaultValue() {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates this setting's value with the one stored in the given preference map.
|
||||||
|
* @param preferences the given preference map that may contain the value to set.
|
||||||
|
* @throws ClassCastException if the value to set is not of the same type as the one supported
|
||||||
|
* by this setting.
|
||||||
|
*/
|
||||||
|
public void updateValue(MapProblemPreference preferences) {
|
||||||
|
IProblemPreference childDescriptor = preferences.getChildDescriptor(descriptor.getKey());
|
||||||
|
if (childDescriptor != null) {
|
||||||
|
value = valueType.cast(childDescriptor.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.internal.externaltool;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.codan.core.cxx.internal.externaltool.Messages.ConfigurationSettings_args_format;
|
||||||
|
import static org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType.TYPE_STRING;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.externaltool.SingleConfigurationSetting;
|
||||||
|
import org.eclipse.cdt.codan.core.param.BasicProblemPreference;
|
||||||
|
import org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User-configurable setting that specifies the arguments to pass when invoking the external tool.
|
||||||
|
* The arguments are stored in a single {@code String}.
|
||||||
|
*/
|
||||||
|
public class ArgsSetting extends SingleConfigurationSetting<String> {
|
||||||
|
static final String KEY = "externalToolArgs"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param externalToolName the name of the external tool. The name of the external tool is
|
||||||
|
* used in the label of this setting's input field.
|
||||||
|
* @param defaultValue the default value of the setting.
|
||||||
|
*/
|
||||||
|
public ArgsSetting(String externalToolName, String defaultValue) {
|
||||||
|
super(newPreferenceDescriptor(externalToolName), defaultValue, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IProblemPreferenceDescriptor newPreferenceDescriptor(String externalToolName) {
|
||||||
|
String label = String.format(ConfigurationSettings_args_format, externalToolName);
|
||||||
|
return new BasicProblemPreference(KEY, label, TYPE_STRING);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.internal.externaltool;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command to execute to invoke an external tool.
|
||||||
|
*/
|
||||||
|
class Command {
|
||||||
|
private final IPath path;
|
||||||
|
private final String[] args;
|
||||||
|
|
||||||
|
Command(IPath path, String[] args) {
|
||||||
|
this.path = path;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPath getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] getArgs() {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.internal.externaltool;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.externaltool.ArgsSeparator;
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.externaltool.ConfigurationSettings;
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.externaltool.InvocationParameters;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the command to use to invoke an external tool.
|
||||||
|
*/
|
||||||
|
class CommandBuilder {
|
||||||
|
Command buildCommand(InvocationParameters parameters, ConfigurationSettings settings,
|
||||||
|
ArgsSeparator argsSeparator) {
|
||||||
|
IPath executablePath = executablePath(settings);
|
||||||
|
String[] args = argsToPass(parameters, settings, argsSeparator);
|
||||||
|
return new Command(executablePath, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IPath executablePath(ConfigurationSettings configurationSettings) {
|
||||||
|
File executablePath = configurationSettings.getPath().getValue();
|
||||||
|
return new Path(executablePath.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] argsToPass(InvocationParameters parameters,
|
||||||
|
ConfigurationSettings configurationSettings, ArgsSeparator argsSeparator) {
|
||||||
|
String actualFilePath = parameters.getActualFilePath();
|
||||||
|
String[] args = configuredArgs(configurationSettings, argsSeparator);
|
||||||
|
return addFilePathToArgs(actualFilePath, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] configuredArgs(ConfigurationSettings settings, ArgsSeparator argsSeparator) {
|
||||||
|
String args = settings.getArgs().getValue();
|
||||||
|
return argsSeparator.splitArguments(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] addFilePathToArgs(String actualFilePath, String[] configuredArgs) {
|
||||||
|
int argCount = configuredArgs.length;
|
||||||
|
String[] allArgs = new String[argCount + 1];
|
||||||
|
allArgs[0] = actualFilePath;
|
||||||
|
// Copy arguments
|
||||||
|
System.arraycopy(configuredArgs, 0, allArgs, 1, argCount);
|
||||||
|
return allArgs;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.internal.externaltool;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.externaltool.ArgsSeparator;
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.externaltool.ConfigurationSettings;
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.externaltool.InvocationFailure;
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.externaltool.InvocationParameters;
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
|
import org.eclipse.cdt.core.CommandLauncher;
|
||||||
|
import org.eclipse.cdt.core.ICommandLauncher;
|
||||||
|
import org.eclipse.cdt.core.IConsoleParser;
|
||||||
|
import org.eclipse.cdt.core.resources.IConsole;
|
||||||
|
import org.eclipse.cdt.internal.core.ConsoleOutputSniffer;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes an external tool to perform checks on a single file.
|
||||||
|
*/
|
||||||
|
public class ExternalToolInvoker {
|
||||||
|
private static final String[] ENV = {};
|
||||||
|
private static final NullProgressMonitor NULL_PROGRESS_MONITOR = new NullProgressMonitor();
|
||||||
|
|
||||||
|
private final CommandBuilder commandBuilder = new CommandBuilder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes an external tool.
|
||||||
|
* @param parameters the parameters to pass to the external tool executable.
|
||||||
|
* @param settings user-configurable settings.
|
||||||
|
* @param argsSeparator separates the arguments to pass to the external tool executable. These
|
||||||
|
* arguments are stored in a single {@code String}.
|
||||||
|
* @param parsers parse the output of the external tool.
|
||||||
|
* @throws InvocationFailure if the external tool could not be invoked or if the external tool
|
||||||
|
* itself reports that it cannot be executed (e.g. due to a configuration error).
|
||||||
|
* @throws Throwable if something else goes wrong.
|
||||||
|
*/
|
||||||
|
public void invoke(InvocationParameters parameters, ConfigurationSettings settings,
|
||||||
|
ArgsSeparator argsSeparator, IConsoleParser[] parsers)
|
||||||
|
throws InvocationFailure, Throwable {
|
||||||
|
Command command = commandBuilder.buildCommand(parameters, settings, argsSeparator);
|
||||||
|
try {
|
||||||
|
launchCommand(command, parsers, parameters);
|
||||||
|
} finally {
|
||||||
|
shutDown(parsers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void launchCommand(Command command, IConsoleParser[] parsers,
|
||||||
|
InvocationParameters parameters) throws InvocationFailure, CoreException {
|
||||||
|
IProject project = parameters.getActualFile().getProject();
|
||||||
|
IConsole c = startConsole(project);
|
||||||
|
ConsoleOutputSniffer sniffer =
|
||||||
|
new ConsoleOutputSniffer(c.getOutputStream(), c.getErrorStream(), parsers);
|
||||||
|
ICommandLauncher launcher = commandLauncher(project);
|
||||||
|
Process p = launcher.execute(command.getPath(), command.getArgs(), ENV,
|
||||||
|
parameters.getWorkingDirectory(), NULL_PROGRESS_MONITOR);
|
||||||
|
if (p == null) {
|
||||||
|
throw new InvocationFailure("Unable to launch external tool. Cause unknown."); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
p.getOutputStream().close();
|
||||||
|
} catch (Throwable ignored) {}
|
||||||
|
try {
|
||||||
|
launcher.waitAndRead(sniffer.getOutputStream(), sniffer.getErrorStream(), NULL_PROGRESS_MONITOR);
|
||||||
|
} finally {
|
||||||
|
p.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IConsole startConsole(IProject project) {
|
||||||
|
IConsole console = CCorePlugin.getDefault().getConsole();
|
||||||
|
console.start(project);
|
||||||
|
return console;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ICommandLauncher commandLauncher(IProject project) {
|
||||||
|
ICommandLauncher launcher = new CommandLauncher();
|
||||||
|
launcher.showCommand(true);
|
||||||
|
launcher.setProject(project);
|
||||||
|
return launcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void shutDown(IConsoleParser[] parsers) {
|
||||||
|
for (IConsoleParser parser : parsers) {
|
||||||
|
parser.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.internal.externaltool;
|
||||||
|
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
|
||||||
|
public class Messages extends NLS {
|
||||||
|
public static String ConfigurationSettings_args_format;
|
||||||
|
public static String ConfigurationSettings_path_format;
|
||||||
|
public static String ConfigurationSettings_should_display_output;
|
||||||
|
|
||||||
|
static {
|
||||||
|
NLS.initializeMessages(Messages.class.getName(), Messages.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Messages() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
###############################################################################
|
||||||
|
# Copyright (c) 2012 Google, Inc and others.
|
||||||
|
# All rights reserved. This program and the accompanying materials
|
||||||
|
# are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
# which accompanies this distribution, and is available at
|
||||||
|
# http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
#
|
||||||
|
# Contributors:
|
||||||
|
# Alex Ruiz (Google) - initial API and implementation
|
||||||
|
###############################################################################
|
||||||
|
ConfigurationSettings_args_format=%s Args:
|
||||||
|
ConfigurationSettings_path_format=%s Path:
|
||||||
|
ConfigurationSettings_should_display_output=Display Output in Console
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.internal.externaltool;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.codan.core.cxx.internal.externaltool.Messages.ConfigurationSettings_path_format;
|
||||||
|
import static org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType.TYPE_FILE;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.externaltool.SingleConfigurationSetting;
|
||||||
|
import org.eclipse.cdt.codan.core.param.BasicProblemPreference;
|
||||||
|
import org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User-configurable setting that specifies the path and name of an external tool's executable.
|
||||||
|
*/
|
||||||
|
public class PathSetting extends SingleConfigurationSetting<File> {
|
||||||
|
static final String KEY = "externalToolPath"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param externalToolName the name of the external tool. The name of the external tool is
|
||||||
|
* used in the label of this setting's input field.
|
||||||
|
* @param defaultValue the default value of the setting.
|
||||||
|
*/
|
||||||
|
public PathSetting(String externalToolName, File defaultValue) {
|
||||||
|
super(newPreferenceDescriptor(externalToolName), defaultValue, File.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IProblemPreferenceDescriptor newPreferenceDescriptor(String externalToolName) {
|
||||||
|
String label = String.format(ConfigurationSettings_path_format, externalToolName);
|
||||||
|
return new BasicProblemPreference(KEY, label, TYPE_FILE);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2009, 2011 Alena Laskavaia
|
* Copyright (c) 2009, 2012 Alena Laskavaia
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -70,12 +70,16 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Run the checker only if the index is fully initialized. Otherwise it may produce
|
||||||
|
// false positives.
|
||||||
|
if (modelCache.getIndex().isFullyInitialized()) {
|
||||||
IASTTranslationUnit ast = modelCache.getAST();
|
IASTTranslationUnit ast = modelCache.getAST();
|
||||||
if (ast != null) {
|
if (ast != null) {
|
||||||
synchronized (ast) {
|
synchronized (ast) {
|
||||||
processAst(ast);
|
processAst(ast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
Activator.log(e);
|
Activator.log(e);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -83,16 +87,19 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* (non-Javadoc)
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see IRunnableInEditorChecker#processModel(Object, ICheckerInvocationContext)
|
* @see IRunnableInEditorChecker#processModel(Object, ICheckerInvocationContext)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized void processModel(Object model, ICheckerInvocationContext context) {
|
public synchronized void processModel(Object model, ICheckerInvocationContext context) {
|
||||||
if (model instanceof IASTTranslationUnit) {
|
if (model instanceof IASTTranslationUnit) {
|
||||||
setContext(context);
|
|
||||||
IASTTranslationUnit ast = (IASTTranslationUnit) model;
|
IASTTranslationUnit ast = (IASTTranslationUnit) model;
|
||||||
|
// Run the checker only if the index was fully initialized when the file was parsed.
|
||||||
|
// Otherwise the checker may produce false positives.
|
||||||
|
if (ast.isBasedOnIncompleteIndex())
|
||||||
|
return;
|
||||||
|
|
||||||
|
setContext(context);
|
||||||
synchronized (context) {
|
synchronized (context) {
|
||||||
modelCache = context.get(CxxModelsCache.class);
|
modelCache = context.get(CxxModelsCache.class);
|
||||||
if (modelCache == null) {
|
if (modelCache == null) {
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class CxxModelsCache implements ICodanDisposable {
|
||||||
return cfg;
|
return cfg;
|
||||||
cfg = CxxControlFlowGraph.build(func);
|
cfg = CxxControlFlowGraph.build(func);
|
||||||
// TODO(Alena Laskavaia): Change to LRU.
|
// TODO(Alena Laskavaia): Change to LRU.
|
||||||
if (cfgmap.size() > 20) { // if too many function better drop the cash
|
if (cfgmap.size() > 20) { // if too many function better drop the cache
|
||||||
cfgmap.clear();
|
cfgmap.clear();
|
||||||
}
|
}
|
||||||
cfgmap.put(func, cfg);
|
cfgmap.put(func, cfg);
|
||||||
|
|
|
@ -100,4 +100,37 @@ public class CxxAstUtilsTest extends CodanFastCxxAstTestCase {
|
||||||
assertTrue((Boolean) result[0]);
|
assertTrue((Boolean) result[0]);
|
||||||
assertFalse((Boolean) result[1]);
|
assertFalse((Boolean) result[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//void f() __attribute__((noreturn));
|
||||||
|
//
|
||||||
|
//int test() {
|
||||||
|
// a();
|
||||||
|
// f();
|
||||||
|
// exit(0);
|
||||||
|
//}
|
||||||
|
public void testExitStatement() throws IOException {
|
||||||
|
String code = getAboveComment();
|
||||||
|
IASTTranslationUnit tu = parse(code);
|
||||||
|
final Object result[] = new Object[4];
|
||||||
|
ASTVisitor astVisitor = new ASTVisitor() {
|
||||||
|
int i;
|
||||||
|
{
|
||||||
|
shouldVisitStatements = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTStatement stmt) {
|
||||||
|
boolean check = CxxAstUtils.isExitStatement(stmt);
|
||||||
|
result[i] = check;
|
||||||
|
i++;
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
tu.accept(astVisitor);
|
||||||
|
assertNotNull("Stmt not found", result[0]); //$NON-NLS-1$
|
||||||
|
assertFalse((Boolean) result[0]); // compound body
|
||||||
|
assertFalse((Boolean) result[1]);
|
||||||
|
assertTrue((Boolean) result[2]);
|
||||||
|
assertTrue((Boolean) result[3]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.externaltool;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for <code>{@link ArgsSeparator}</code>.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
public class ArgsSeparatorTest extends TestCase {
|
||||||
|
private ArgsSeparator separator;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() {
|
||||||
|
separator = new ArgsSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWithSpaceAsDelimiter() {
|
||||||
|
String[] args = separator.splitArguments("abc def ghi");
|
||||||
|
assertArrayEquals(new String[] { "abc", "def", "ghi" }, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWithSingleQuote() {
|
||||||
|
String[] args = separator.splitArguments("abc 'def ghi' jkl");
|
||||||
|
assertArrayEquals(new String[] { "abc", "def ghi", "jkl" }, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWithDoubleQuote() {
|
||||||
|
String[] args = separator.splitArguments("abc \"def ghi\" jkl");
|
||||||
|
assertArrayEquals(new String[] { "abc", "def ghi", "jkl" }, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWithEscapedSingleQuote() {
|
||||||
|
String[] args = separator.splitArguments("abc 'def \\' ghi' jkl");
|
||||||
|
assertArrayEquals(new String[] { "abc", "def \\' ghi", "jkl" }, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWithEscapedDoubleQuote() {
|
||||||
|
String[] args = separator.splitArguments("abc 'def \\\" ghi' jkl");
|
||||||
|
assertArrayEquals(new String[] { "abc", "def \\\" ghi", "jkl" }, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -298,4 +298,16 @@ public class ReturnCheckerTest extends CheckerTestCase {
|
||||||
loadCodeAndRunCpp(getAboveComment());
|
loadCodeAndRunCpp(getAboveComment());
|
||||||
checkNoErrors();
|
checkNoErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//void f() __attribute__((noreturn));
|
||||||
|
//
|
||||||
|
//int test() {
|
||||||
|
// f();
|
||||||
|
//}
|
||||||
|
|
||||||
|
public void testNoReturn() {
|
||||||
|
loadCodeAndRun(getAboveComment());
|
||||||
|
checkNoErrors();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -19,7 +19,8 @@ Export-Package: org.eclipse.cdt.codan.core,
|
||||||
x-friends:="org.eclipse.cdt.codan.core,
|
x-friends:="org.eclipse.cdt.codan.core,
|
||||||
org.eclipse.cdt.codan.core.cxx,
|
org.eclipse.cdt.codan.core.cxx,
|
||||||
org.eclipse.cdt.codan.core.test,
|
org.eclipse.cdt.codan.core.test,
|
||||||
org.eclipse.cdt.codan.ui",
|
org.eclipse.cdt.codan.ui,
|
||||||
|
org.eclipse.cdt.codan.ui.cxx",
|
||||||
org.eclipse.cdt.codan.internal.core.cfg;x-friends:="org.eclipse.cdt.codan.core.cxx",
|
org.eclipse.cdt.codan.internal.core.cfg;x-friends:="org.eclipse.cdt.codan.core.cxx",
|
||||||
org.eclipse.cdt.codan.internal.core.model;
|
org.eclipse.cdt.codan.internal.core.model;
|
||||||
x-friends:="org.eclipse.cdt.codan.core.cxx,
|
x-friends:="org.eclipse.cdt.codan.core.cxx,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<?eclipse version="3.4"?>
|
<?eclipse version="3.4"?>
|
||||||
<plugin>
|
<plugin>
|
||||||
<extension-point id="checkers" name="%extension-point.name.CodeAnalysis" schema="schema/checkers.exsd"/>
|
<extension-point id="checkers" name="%extension-point.name.CodeAnalysis" schema="schema/checkers.exsd"/>
|
||||||
|
<extension-point id="checkerEnablement" name="Verification of checker enablement" schema="schema/checkerEnablement.exsd"/>
|
||||||
|
|
||||||
<extension
|
<extension
|
||||||
id="codanBuilder"
|
id="codanBuilder"
|
||||||
|
|
106
codan/org.eclipse.cdt.codan.core/schema/checkerEnablement.exsd
Normal file
106
codan/org.eclipse.cdt.codan.core/schema/checkerEnablement.exsd
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!-- Schema file written by PDE -->
|
||||||
|
<schema targetNamespace="org.eclipse.cdt.codan.core" xmlns="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<annotation>
|
||||||
|
<appinfo>
|
||||||
|
<meta.schema plugin="org.eclipse.cdt.codan.core" id="checkerEnablement" name="Verification of checker enablement"/>
|
||||||
|
</appinfo>
|
||||||
|
<documentation>
|
||||||
|
Verifies that a checker should be executed on a given resource in a given launch mode.
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
<element name="extension">
|
||||||
|
<annotation>
|
||||||
|
<appinfo>
|
||||||
|
<meta.element />
|
||||||
|
</appinfo>
|
||||||
|
</annotation>
|
||||||
|
<complexType>
|
||||||
|
<attribute name="point" type="string" use="required">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
The fully qualified name of this extension point.
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="id" type="string">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
ID of the extension point (Simple ID).
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="name" type="string">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
Name of the extension point.
|
||||||
|
</documentation>
|
||||||
|
<appinfo>
|
||||||
|
<meta.attribute translatable="true"/>
|
||||||
|
</appinfo>
|
||||||
|
</annotation>
|
||||||
|
</attribute>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="verifier">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
Specifies the implementation of ICheckerEnablementVerifier to use.
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
<complexType>
|
||||||
|
<attribute name="class" type="string" use="required">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
The implementation of ICheckerEnablementVerifier to use.
|
||||||
|
</documentation>
|
||||||
|
<appinfo>
|
||||||
|
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.codan.internal.core.ICheckerEnablementVerifier"/>
|
||||||
|
</appinfo>
|
||||||
|
</annotation>
|
||||||
|
</attribute>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<annotation>
|
||||||
|
<appinfo>
|
||||||
|
<meta.section type="since"/>
|
||||||
|
</appinfo>
|
||||||
|
<documentation>
|
||||||
|
2.1
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
<annotation>
|
||||||
|
<appinfo>
|
||||||
|
<meta.section type="examples"/>
|
||||||
|
</appinfo>
|
||||||
|
<documentation>
|
||||||
|
<extension point="org.eclipse.cdt.codan.core.checkerEnablement">
|
||||||
|
<verifier class="org.eclipse.cdt.codan.internal.ui.CheckerEnablementVerifier" />
|
||||||
|
</extension>
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
<annotation>
|
||||||
|
<appinfo>
|
||||||
|
<meta.section type="apiinfo"/>
|
||||||
|
</appinfo>
|
||||||
|
<documentation>
|
||||||
|
Plug-ins that want to extend this extension point must implement org.eclipse.cdt.codan.internal.core.ICheckerEnablementVerifier interface.
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
<annotation>
|
||||||
|
<appinfo>
|
||||||
|
<meta.section type="implementation"/>
|
||||||
|
</appinfo>
|
||||||
|
<documentation>
|
||||||
|
The default implementation of this extension point is org.eclipse.cdt.codan.internal.ui.CheckerEnablementVerifier.
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
|
||||||
|
</schema>
|
|
@ -11,15 +11,15 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.codan.core.model;
|
package org.eclipse.cdt.codan.core.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.cdt.codan.core.CodanRuntime;
|
import org.eclipse.cdt.codan.core.CodanRuntime;
|
||||||
import org.eclipse.cdt.codan.internal.core.CheckersRegistry;
|
import org.eclipse.cdt.codan.internal.core.CheckersRegistry;
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.resources.IResource;
|
import org.eclipse.core.resources.IResource;
|
||||||
import org.eclipse.core.runtime.OperationCanceledException;
|
import org.eclipse.core.runtime.OperationCanceledException;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience implementation of IChecker interface. Has a default
|
* Convenience implementation of IChecker interface. Has a default
|
||||||
* implementation for common methods.
|
* implementation for common methods.
|
||||||
|
@ -37,10 +37,7 @@ public abstract class AbstractChecker implements IChecker {
|
||||||
public AbstractChecker() {
|
public AbstractChecker() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Deprecated
|
||||||
* @return true if checker is enabled in context of resource, if returns
|
|
||||||
* false checker's "processResource" method won't be called
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean enabledInContext(IResource res) {
|
public boolean enabledInContext(IResource res) {
|
||||||
return res.getType() == IResource.FILE;
|
return res.getType() == IResource.FILE;
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011, 2012 Alena Laskavaia 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
* Alex Ruiz (Google)
|
||||||
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.codan.core.model;
|
package org.eclipse.cdt.codan.core.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,19 +23,25 @@ package org.eclipse.cdt.codan.core.model;
|
||||||
*/
|
*/
|
||||||
public enum CheckerLaunchMode {
|
public enum CheckerLaunchMode {
|
||||||
/**
|
/**
|
||||||
* checker run when full build is running
|
* Checker runs when full build is running.
|
||||||
*/
|
*/
|
||||||
RUN_ON_FULL_BUILD,
|
RUN_ON_FULL_BUILD,
|
||||||
/**
|
/**
|
||||||
* checker run when incremental build is running
|
* Checker runs when incremental build is running.
|
||||||
*/
|
*/
|
||||||
RUN_ON_INC_BUILD,
|
RUN_ON_INC_BUILD,
|
||||||
/**
|
/**
|
||||||
* checker run in editor as you type
|
* Checker runs when a file is saved or opened. Checker will not run if the file is an editor
|
||||||
|
* with unsaved changes.
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
RUN_ON_FILE_SAVE,
|
||||||
|
/**
|
||||||
|
* Checker runs in editor as you type.
|
||||||
*/
|
*/
|
||||||
RUN_AS_YOU_TYPE,
|
RUN_AS_YOU_TYPE,
|
||||||
/**
|
/**
|
||||||
* checker run when explicit command is given
|
* Checker runs when explicit command is given.
|
||||||
*/
|
*/
|
||||||
RUN_ON_DEMAND,
|
RUN_ON_DEMAND,
|
||||||
}
|
}
|
|
@ -72,7 +72,10 @@ public interface IChecker {
|
||||||
*
|
*
|
||||||
* @param resource the resource to run on.
|
* @param resource the resource to run on.
|
||||||
* @return true if checker should be run on this resource.
|
* @return true if checker should be run on this resource.
|
||||||
|
* @deprecated Replaced by {@code CheckersRegistry.isCheckerEnabled((IChecker IResource, CheckerLaunchMode)}
|
||||||
|
* and {@code ICheckerEnablementVerifier.isCheckerEnabled(IChecker IResource, CheckerLaunchMode)}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
boolean enabledInContext(IResource resource);
|
boolean enabledInContext(IResource resource);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.param;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preferences that can be shared among several problems.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public class SharedRootProblemPreference extends RootProblemPreference {
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
SharedRootProblemPreference map = (SharedRootProblemPreference) super.clone();
|
||||||
|
// alruiz: sharing the internal hash is the only way I could make this work.
|
||||||
|
map.hash = hash;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.cdt.codan.core.CodanCorePlugin;
|
import org.eclipse.cdt.codan.core.CodanCorePlugin;
|
||||||
|
@ -51,7 +52,9 @@ import org.osgi.service.prefs.Preferences;
|
||||||
public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
||||||
private static final String NAME_ATTR = "name"; //$NON-NLS-1$
|
private static final String NAME_ATTR = "name"; //$NON-NLS-1$
|
||||||
private static final String ID_ATTR = "id"; //$NON-NLS-1$
|
private static final String ID_ATTR = "id"; //$NON-NLS-1$
|
||||||
private static final String EXTENSION_POINT_NAME = "checkers"; //$NON-NLS-1$
|
private static final String CLASS_ATTR = "class"; //$NON-NLS-1$
|
||||||
|
private static final String CHECKERS_EXTENSION_POINT_NAME = "checkers"; //$NON-NLS-1$
|
||||||
|
private static final String CHECKER_ENABLEMENT_EXTENSION_POINT_NAME = "checkerEnablement"; //$NON-NLS-1$
|
||||||
private static final String CHECKER_ELEMENT = "checker"; //$NON-NLS-1$
|
private static final String CHECKER_ELEMENT = "checker"; //$NON-NLS-1$
|
||||||
private static final String PROBLEM_ELEMENT = "problem"; //$NON-NLS-1$
|
private static final String PROBLEM_ELEMENT = "problem"; //$NON-NLS-1$
|
||||||
private static final String CATEGORY_ELEMENT = "category"; //$NON-NLS-1$
|
private static final String CATEGORY_ELEMENT = "category"; //$NON-NLS-1$
|
||||||
|
@ -60,19 +63,21 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
||||||
private Collection<IChecker> checkers = new ArrayList<IChecker>();
|
private Collection<IChecker> checkers = new ArrayList<IChecker>();
|
||||||
private static CheckersRegistry instance;
|
private static CheckersRegistry instance;
|
||||||
private static boolean initialized = false;
|
private static boolean initialized = false;
|
||||||
private HashMap<Object, IProblemProfile> profiles = new HashMap<Object, IProblemProfile>();
|
private final Map<Object, IProblemProfile> profiles = new HashMap<Object, IProblemProfile>();
|
||||||
private HashMap<IChecker, Collection<IProblem>> problemList = new HashMap<IChecker, Collection<IProblem>>();
|
private final Map<IChecker, Collection<IProblem>> problemList = new HashMap<IChecker, Collection<IProblem>>();
|
||||||
private Map<String, IChecker> problemCheckerMapping = new HashMap<String, IChecker>();
|
private final Map<String, IChecker> problemCheckerMapping = new HashMap<String, IChecker>();
|
||||||
|
private final List<ICheckerEnablementVerifier> checkerEnablementVerifiers = new ArrayList<ICheckerEnablementVerifier>();
|
||||||
|
|
||||||
private CheckersRegistry() {
|
private CheckersRegistry() {
|
||||||
instance = this;
|
instance = this;
|
||||||
profiles.put(DEFAULT, new ProblemProfile(DEFAULT));
|
profiles.put(DEFAULT, new ProblemProfile(DEFAULT));
|
||||||
readCheckersRegistry();
|
readCheckersRegistry();
|
||||||
|
readCheckerEnablementVerifier();
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readCheckersRegistry() {
|
private void readCheckersRegistry() {
|
||||||
IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint(CodanCorePlugin.PLUGIN_ID, EXTENSION_POINT_NAME);
|
IExtensionPoint ep = getExtensionPoint(CHECKERS_EXTENSION_POINT_NAME);
|
||||||
if (ep == null)
|
if (ep == null)
|
||||||
return;
|
return;
|
||||||
IConfigurationElement[] elements = ep.getConfigurationElements();
|
IConfigurationElement[] elements = ep.getConfigurationElements();
|
||||||
|
@ -141,7 +146,7 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
||||||
name = id;
|
name = id;
|
||||||
IChecker checkerObj = null;
|
IChecker checkerObj = null;
|
||||||
try {
|
try {
|
||||||
Object checker = configurationElement.createExecutableExtension("class"); //$NON-NLS-1$
|
Object checker = configurationElement.createExecutableExtension(CLASS_ATTR);
|
||||||
checkerObj = (IChecker) checker;
|
checkerObj = (IChecker) checker;
|
||||||
addChecker(checkerObj);
|
addChecker(checkerObj);
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
|
@ -236,6 +241,21 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
||||||
return elementValue;
|
return elementValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readCheckerEnablementVerifier() {
|
||||||
|
IExtensionPoint ep = getExtensionPoint(CHECKER_ENABLEMENT_EXTENSION_POINT_NAME);
|
||||||
|
for (IConfigurationElement ce : ep.getConfigurationElements()) {
|
||||||
|
try {
|
||||||
|
checkerEnablementVerifiers.add((ICheckerEnablementVerifier) ce.createExecutableExtension(CLASS_ATTR));
|
||||||
|
} catch (CoreException e) {
|
||||||
|
CodanCorePlugin.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IExtensionPoint getExtensionPoint(String extensionPointName) {
|
||||||
|
return Platform.getExtensionRegistry().getExtensionPoint(CodanCorePlugin.PLUGIN_ID, extensionPointName);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
|
@ -459,7 +479,15 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
||||||
* @param mode
|
* @param mode
|
||||||
* @return <code>true</code> if the checker should run.
|
* @return <code>true</code> if the checker should run.
|
||||||
*/
|
*/
|
||||||
public boolean isCheckerEnabledForLaunchMode(IChecker checker, IResource resource, CheckerLaunchMode mode) {
|
public boolean isCheckerEnabled(IChecker checker, IResource resource, CheckerLaunchMode mode) {
|
||||||
|
if (resource.getType() != IResource.FILE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (ICheckerEnablementVerifier verifier : checkerEnablementVerifiers) {
|
||||||
|
if (!verifier.isCheckerEnabled(checker, resource, mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
IProblemProfile resourceProfile = getResourceProfile(resource);
|
IProblemProfile resourceProfile = getResourceProfile(resource);
|
||||||
Collection<IProblem> refProblems = getRefProblems(checker);
|
Collection<IProblem> refProblems = getRefProblems(checker);
|
||||||
boolean enabled = false;
|
boolean enabled = false;
|
||||||
|
|
|
@ -140,8 +140,7 @@ public class CodanBuilder extends IncrementalProjectBuilder implements ICodanBui
|
||||||
if (monitor.isCanceled())
|
if (monitor.isCanceled())
|
||||||
return;
|
return;
|
||||||
if (doesCheckerSupportLaunchMode(checker, checkerLaunchMode)
|
if (doesCheckerSupportLaunchMode(checker, checkerLaunchMode)
|
||||||
&& checker.enabledInContext(resource)
|
&& chegistry.isCheckerEnabled(checker, resource, checkerLaunchMode)) {
|
||||||
&& chegistry.isCheckerEnabledForLaunchMode(checker, resource, checkerLaunchMode)) {
|
|
||||||
synchronized (checker) {
|
synchronized (checker) {
|
||||||
try {
|
try {
|
||||||
checker.before(resource);
|
checker.before(resource);
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.internal.core;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.model.CheckerLaunchMode;
|
||||||
|
import org.eclipse.cdt.codan.core.model.IChecker;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that an <code>{@link IChecker}</code> can be invoked.
|
||||||
|
*/
|
||||||
|
public interface ICheckerEnablementVerifier {
|
||||||
|
/**
|
||||||
|
* Indicates whether the given code checker can be invoked on the given resource in the given
|
||||||
|
* launch mode.
|
||||||
|
* @param checker the given code checker.
|
||||||
|
* @param resource the resource to be checked.
|
||||||
|
* @param mode the current launch mode.
|
||||||
|
* @return {@code true} if the given code checker can be invoked, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isCheckerEnabled(IChecker checker, IResource resource, CheckerLaunchMode mode);
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
<classpathentry kind="src" path="src"/>
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||||
<classpathentry kind="output" path="bin"/>
|
<classpathentry kind="output" path="bin"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#Wed Feb 23 19:44:01 EST 2011
|
|
||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
|
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
|
||||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
|
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
|
||||||
|
@ -70,7 +69,7 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disa
|
||||||
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
||||||
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
||||||
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||||
org.eclipse.jdt.core.compiler.source=1.5
|
org.eclipse.jdt.core.compiler.source=1.6
|
||||||
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
||||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
|
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
|
||||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
|
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
|
||||||
|
@ -149,9 +148,12 @@ org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
|
||||||
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
|
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
|
||||||
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
|
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
|
||||||
org.eclipse.jdt.core.formatter.indentation.size=4
|
org.eclipse.jdt.core.formatter.indentation.size=4
|
||||||
|
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
|
||||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
|
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
|
||||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
|
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
|
||||||
|
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
|
||||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
|
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
|
||||||
|
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
|
||||||
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
|
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
|
||||||
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
|
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
|
||||||
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
|
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
|
||||||
|
|
|
@ -11,7 +11,7 @@ Require-Bundle: org.eclipse.core.runtime,
|
||||||
org.eclipse.cdt.core,
|
org.eclipse.cdt.core,
|
||||||
org.eclipse.core.resources,
|
org.eclipse.core.resources,
|
||||||
org.eclipse.cdt.codan.ui;bundle-version="1.0.0"
|
org.eclipse.cdt.codan.ui;bundle-version="1.0.0"
|
||||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Export-Package: org.eclipse.cdt.codan.examples,
|
Export-Package: org.eclipse.cdt.codan.examples,
|
||||||
org.eclipse.cdt.codan.examples.checkers,
|
org.eclipse.cdt.codan.examples.checkers,
|
||||||
|
|
|
@ -11,3 +11,14 @@
|
||||||
#Properties file for org.eclipse.cdt.codan.examples
|
#Properties file for org.eclipse.cdt.codan.examples
|
||||||
Bundle-Vendor = Eclipse CDT
|
Bundle-Vendor = Eclipse CDT
|
||||||
Bundle-Name = Code Analysis Checker Examples
|
Bundle-Name = Code Analysis Checker Examples
|
||||||
|
|
||||||
|
checker.name.Cppcheck = Cppcheck
|
||||||
|
problem.description.Cppcheck.Error = Errors reported by Cppcheck (http://cppcheck.sourceforge.net/)
|
||||||
|
problem.name.Cppcheck.Error = Errors
|
||||||
|
problem.description.Cppcheck.Warning = Warnings reported by Cppcheck (http://cppcheck.sourceforge.net/)
|
||||||
|
problem.name.Cppcheck.Warning = Warnings
|
||||||
|
problem.description.Cppcheck.Syntax = Syntax problems reported by Cppcheck (http://cppcheck.sourceforge.net/)
|
||||||
|
problem.name.Cppcheck.Syntax = Syntax Problems
|
||||||
|
problem.messagePattern.Cppcheck.all = {0}
|
||||||
|
|
||||||
|
errorparser.name.cppcheck = Cppcheck Output Parser
|
|
@ -42,6 +42,42 @@
|
||||||
name="Search string error">
|
name="Search string error">
|
||||||
</problem>
|
</problem>
|
||||||
</checker>
|
</checker>
|
||||||
|
<category
|
||||||
|
id="org.eclipse.cdt.codan.checkers.cppcheck"
|
||||||
|
name="%checker.name.Cppcheck">
|
||||||
|
</category>
|
||||||
|
<checker
|
||||||
|
class="org.eclipse.cdt.codan.examples.checkers.cppcheck.CppcheckChecker"
|
||||||
|
id="org.eclipse.cdt.codan.checkers.CppcheckChecker"
|
||||||
|
name="Cppcheck">
|
||||||
|
<problem
|
||||||
|
category="org.eclipse.cdt.codan.checkers.cppcheck"
|
||||||
|
defaultEnabled="false"
|
||||||
|
defaultSeverity="Error"
|
||||||
|
description="%problem.description.Cppcheck.Error"
|
||||||
|
id="org.eclipse.cdt.codan.checkers.cppcheck.error"
|
||||||
|
messagePattern="%problem.messagePattern.Cppcheck.all"
|
||||||
|
name="%problem.name.Cppcheck.Error">
|
||||||
|
</problem>
|
||||||
|
<problem
|
||||||
|
category="org.eclipse.cdt.codan.checkers.cppcheck"
|
||||||
|
defaultEnabled="false"
|
||||||
|
defaultSeverity="Warning"
|
||||||
|
description="%problem.description.Cppcheck.Warning"
|
||||||
|
id="org.eclipse.cdt.codan.checkers.cppcheck.warning"
|
||||||
|
messagePattern="%problem.messagePattern.Cppcheck.all"
|
||||||
|
name="%problem.name.Cppcheck.Warning">
|
||||||
|
</problem>
|
||||||
|
<problem
|
||||||
|
category="org.eclipse.cdt.codan.checkers.cppcheck"
|
||||||
|
defaultEnabled="false"
|
||||||
|
defaultSeverity="Warning"
|
||||||
|
description="%problem.description.Cppcheck.Syntax"
|
||||||
|
id="org.eclipse.cdt.codan.checkers.cppcheck.style"
|
||||||
|
messagePattern="%problem.messagePattern.Cppcheck.all"
|
||||||
|
name="%problem.name.Cppcheck.Syntax">
|
||||||
|
</problem>
|
||||||
|
</checker>
|
||||||
</extension>
|
</extension>
|
||||||
<extension
|
<extension
|
||||||
point="org.eclipse.cdt.codan.ui.codanProblemDetails">
|
point="org.eclipse.cdt.codan.ui.codanProblemDetails">
|
||||||
|
@ -54,4 +90,17 @@
|
||||||
>
|
>
|
||||||
</problemDetails>
|
</problemDetails>
|
||||||
</extension>
|
</extension>
|
||||||
|
<extension
|
||||||
|
id="CodanErrorParser"
|
||||||
|
name="name"
|
||||||
|
point="org.eclipse.cdt.core.ErrorParser">
|
||||||
|
<errorparser
|
||||||
|
class="org.eclipse.cdt.codan.examples.checkers.cppcheck.CppcheckOutputParser"
|
||||||
|
id="org.eclipse.cdt.codan.checkers.externaltool.CppcheckChecker"
|
||||||
|
name="%errorparser.name.cppcheck">
|
||||||
|
<context
|
||||||
|
type="codan">
|
||||||
|
</context>
|
||||||
|
</errorparser>
|
||||||
|
</extension>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.examples.checkers.cppcheck;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.externaltool.AbstractExternalToolBasedChecker;
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.externaltool.ConfigurationSettings;
|
||||||
|
import org.eclipse.cdt.core.ProblemMarkerInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checker that invokes <a href="http://cppcheck.sourceforge.net/">Cppcheck</a> when a C/C++ file is
|
||||||
|
* saved.
|
||||||
|
*/
|
||||||
|
public class CppcheckChecker extends AbstractExternalToolBasedChecker {
|
||||||
|
private static final String TOOL_NAME = Messages.CppcheckChecker_toolName;
|
||||||
|
private static final String EXECUTABLE_NAME = "cppcheck"; //$NON-NLS-1$
|
||||||
|
private static final String DEFAULT_ARGS = "--enable=all"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static final String DESCRIPTION_FORMAT = "[" + TOOL_NAME + "] %s"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
private static final String ERROR_PROBLEM_ID;
|
||||||
|
|
||||||
|
// key: severity (error, warning, etc.) - value : problem ID associated to severity
|
||||||
|
private static final Map<Severity, String> PROBLEM_IDS = new HashMap<Severity, String>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
ERROR_PROBLEM_ID = addProblemId(Severity.ERROR);
|
||||||
|
addProblemId(Severity.WARNING);
|
||||||
|
addProblemId(Severity.STYLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String addProblemId(Severity severity) {
|
||||||
|
String problemId = "org.eclipse.cdt.codan.checkers.cppcheck." + severity; //$NON-NLS-1$
|
||||||
|
PROBLEM_IDS.put(severity, problemId);
|
||||||
|
return problemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CppcheckChecker() {
|
||||||
|
super(new ConfigurationSettings(TOOL_NAME, new File(EXECUTABLE_NAME), DEFAULT_ARGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getParserIDs() {
|
||||||
|
return new String[] { "org.eclipse.cdt.codan.checkers.externaltool.CppcheckChecker" }; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addMarker(ProblemMarkerInfo info) {
|
||||||
|
Severity severity = Severity.findSeverity(info.severity);
|
||||||
|
String description = String.format(DESCRIPTION_FORMAT, info.description);
|
||||||
|
reportProblem(PROBLEM_IDS.get(severity), createProblemLocation(info), description);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getReferenceProblemId() {
|
||||||
|
return ERROR_PROBLEM_ID;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.examples.checkers.cppcheck;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.ErrorParserManager;
|
||||||
|
import org.eclipse.cdt.core.IErrorParser;
|
||||||
|
import org.eclipse.cdt.core.ProblemMarkerInfo;
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the output of Cppcheck.
|
||||||
|
*/
|
||||||
|
public class CppcheckOutputParser implements IErrorParser {
|
||||||
|
// sample line to parse:
|
||||||
|
//
|
||||||
|
// [/src/HelloWorld.cpp:19]: (style) The scope of the variable 'i' can be reduced
|
||||||
|
// ----------1--------- -2 --3-- ------------------4-------------------------
|
||||||
|
//
|
||||||
|
// groups:
|
||||||
|
// 1: file path and name
|
||||||
|
// 2: line where problem was found
|
||||||
|
// 3: problem severity
|
||||||
|
// 4: problem description
|
||||||
|
private static Pattern pattern = Pattern.compile("\\[(.*):(\\d+)\\]:\\s*\\((.*)\\)\\s*(.*)"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean processLine(String line, ErrorParserManager eoParser) {
|
||||||
|
Matcher matcher = pattern.matcher(line);
|
||||||
|
if (!matcher.matches()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
IFile fileName = eoParser.findFileName(matcher.group(1));
|
||||||
|
if (fileName != null) {
|
||||||
|
int lineNumber = Integer.parseInt(matcher.group(2));
|
||||||
|
String description = matcher.group(4);
|
||||||
|
int severity = Severity.findSeverityCode(matcher.group(3));
|
||||||
|
ProblemMarkerInfo info = new ProblemMarkerInfo(fileName, lineNumber, description, severity, null);
|
||||||
|
eoParser.addProblemMarker(info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.examples.checkers.cppcheck;
|
||||||
|
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
|
||||||
|
public class Messages extends NLS {
|
||||||
|
public static String CppcheckChecker_toolName;
|
||||||
|
|
||||||
|
static {
|
||||||
|
// initialize resource bundle
|
||||||
|
Class<Messages> clazz = Messages.class;
|
||||||
|
NLS.initializeMessages(clazz.getName(), clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Messages() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
###############################################################################
|
||||||
|
# Copyright (c) 2012 Google, Inc and others.
|
||||||
|
# All rights reserved. This program and the accompanying materials
|
||||||
|
# are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
# which accompanies this distribution, and is available at
|
||||||
|
# http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
#
|
||||||
|
# Contributors:
|
||||||
|
# Alex Ruiz (Google) - initial API and implementation
|
||||||
|
###############################################################################
|
||||||
|
CppcheckChecker_toolName=Cppcheck
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.examples.checkers.cppcheck;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.IMarkerGenerator;
|
||||||
|
|
||||||
|
enum Severity {
|
||||||
|
ERROR(IMarkerGenerator.SEVERITY_ERROR_RESOURCE, "error"), //$NON-NLS-1$
|
||||||
|
WARNING(IMarkerGenerator.SEVERITY_WARNING, "warning"), //$NON-NLS-1$
|
||||||
|
STYLE(IMarkerGenerator.SEVERITY_INFO, "style"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
private final int code;
|
||||||
|
private final String text;
|
||||||
|
|
||||||
|
private Severity(int code, String text) {
|
||||||
|
this.code = code;
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int findSeverityCode(String text) {
|
||||||
|
for (Severity severity : values()) {
|
||||||
|
if (severity.text.equals(text)) {
|
||||||
|
return severity.code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return STYLE.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Severity findSeverity(int code) {
|
||||||
|
for (Severity severity : values()) {
|
||||||
|
if (severity.code == code) {
|
||||||
|
return severity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return STYLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,8 @@ Require-Bundle: org.eclipse.ui,
|
||||||
org.eclipse.ui.ide,
|
org.eclipse.ui.ide,
|
||||||
org.eclipse.cdt.ui,
|
org.eclipse.cdt.ui,
|
||||||
org.eclipse.core.filesystem,
|
org.eclipse.core.filesystem,
|
||||||
org.eclipse.ui.console
|
org.eclipse.ui.console,
|
||||||
|
org.eclipse.ui.editors
|
||||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Export-Package: org.eclipse.cdt.codan.internal.ui;x-friends:="org.eclipse.cdt.codan.ui.cxx",
|
Export-Package: org.eclipse.cdt.codan.internal.ui;x-friends:="org.eclipse.cdt.codan.ui.cxx",
|
||||||
|
|
|
@ -238,4 +238,8 @@
|
||||||
|
|
||||||
</objectContribution>
|
</objectContribution>
|
||||||
</extension>
|
</extension>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.cdt.codan.core.checkerEnablement">
|
||||||
|
<verifier class="org.eclipse.cdt.codan.internal.ui.CheckerEnablementVerifier" />
|
||||||
|
</extension>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.internal.ui;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.model.CheckerLaunchMode;
|
||||||
|
import org.eclipse.cdt.codan.core.model.IChecker;
|
||||||
|
import org.eclipse.cdt.codan.internal.core.ICheckerEnablementVerifier;
|
||||||
|
import org.eclipse.cdt.codan.ui.CodanEditorUtility;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.ui.IEditorPart;
|
||||||
|
import org.eclipse.ui.IEditorReference;
|
||||||
|
import org.eclipse.ui.IWorkbenchPage;
|
||||||
|
import org.eclipse.ui.IWorkbenchWindow;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.ui.editors.text.TextEditor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of <code>{@link ICheckerEnablementVerifier}</code>.
|
||||||
|
*/
|
||||||
|
public class CheckerEnablementVerifier implements ICheckerEnablementVerifier {
|
||||||
|
@Override
|
||||||
|
public boolean isCheckerEnabled(IChecker checker, IResource resource, CheckerLaunchMode mode) {
|
||||||
|
if (mode != CheckerLaunchMode.RUN_ON_FILE_SAVE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (IWorkbenchWindow window : PlatformUI.getWorkbench().getWorkbenchWindows()) {
|
||||||
|
IWorkbenchPage page = window.getActivePage();
|
||||||
|
for (IEditorReference reference : page.getEditorReferences()) {
|
||||||
|
IEditorPart editor = reference.getEditor(false);
|
||||||
|
if (!CodanEditorUtility.isResourceOpenInEditor(resource, editor)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (editor instanceof TextEditor) {
|
||||||
|
TextEditor textEditor = (TextEditor) editor;
|
||||||
|
return !textEditor.isDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -87,6 +87,7 @@ public class CodanUIMessages extends NLS {
|
||||||
public static String LaunchModesPropertyPage_RunOnDemand;
|
public static String LaunchModesPropertyPage_RunOnDemand;
|
||||||
public static String LaunchModesPropertyPage_RunOnFullBuild;
|
public static String LaunchModesPropertyPage_RunOnFullBuild;
|
||||||
public static String LaunchModesPropertyPage_RunOnIncrementalBuild;
|
public static String LaunchModesPropertyPage_RunOnIncrementalBuild;
|
||||||
|
public static String LaunchModesPropertyPage_RunOnFileSave;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
NLS.initializeMessages(CodanUIMessages.class.getName(), CodanUIMessages.class);
|
NLS.initializeMessages(CodanUIMessages.class.getName(), CodanUIMessages.class);
|
||||||
|
|
|
@ -96,3 +96,4 @@ LaunchModesPropertyPage_RunAsYouType=Run as you type
|
||||||
LaunchModesPropertyPage_RunOnDemand=Run on demand
|
LaunchModesPropertyPage_RunOnDemand=Run on demand
|
||||||
LaunchModesPropertyPage_RunOnFullBuild=Run on full build
|
LaunchModesPropertyPage_RunOnFullBuild=Run on full build
|
||||||
LaunchModesPropertyPage_RunOnIncrementalBuild=Run on incremental build
|
LaunchModesPropertyPage_RunOnIncrementalBuild=Run on incremental build
|
||||||
|
LaunchModesPropertyPage_RunOnFileSave=Run on file save or open
|
||||||
|
|
|
@ -37,7 +37,11 @@ public class LaunchModesPropertyPage extends FieldEditorPreferencePage {
|
||||||
super(GRID);
|
super(GRID);
|
||||||
CheckersRegistry registry = CheckersRegistry.getInstance();
|
CheckersRegistry registry = CheckersRegistry.getInstance();
|
||||||
IChecker checker = registry.getCheckerForProblem(problem);
|
IChecker checker = registry.getCheckerForProblem(problem);
|
||||||
runInEditor = (checker != null) ? Checkers.canCheckerRunAsYouType(checker) : false;
|
if (checker != null) {
|
||||||
|
runInEditor = Checkers.canCheckerRunAsYouType(checker);
|
||||||
|
} else {
|
||||||
|
runInEditor = false;
|
||||||
|
}
|
||||||
setPreferenceStore(prefStore);
|
setPreferenceStore(prefStore);
|
||||||
editors = new ArrayList<FieldEditor>();
|
editors = new ArrayList<FieldEditor>();
|
||||||
}
|
}
|
||||||
|
@ -59,6 +63,7 @@ public class LaunchModesPropertyPage extends FieldEditorPreferencePage {
|
||||||
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_FULL_BUILD.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnFullBuild, getFieldEditorParent()));
|
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_FULL_BUILD.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnFullBuild, getFieldEditorParent()));
|
||||||
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_INC_BUILD.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnIncrementalBuild, getFieldEditorParent()));
|
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_INC_BUILD.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnIncrementalBuild, getFieldEditorParent()));
|
||||||
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_DEMAND.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnDemand, getFieldEditorParent()));
|
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_DEMAND.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnDemand, getFieldEditorParent()));
|
||||||
|
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_ON_FILE_SAVE.name(), CodanUIMessages.LaunchModesPropertyPage_RunOnFileSave, getFieldEditorParent()));
|
||||||
if (runInEditor) {
|
if (runInEditor) {
|
||||||
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_AS_YOU_TYPE.name(), CodanUIMessages.LaunchModesPropertyPage_RunAsYouType, getFieldEditorParent()));
|
addField(new BooleanFieldEditor(CheckerLaunchMode.RUN_AS_YOU_TYPE.name(), CodanUIMessages.LaunchModesPropertyPage_RunAsYouType, getFieldEditorParent()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,4 +201,9 @@ public class EmptyIndexFragment implements IIndexFragment {
|
||||||
public IIndexScope[] getInlineNamespaces() {
|
public IIndexScope[] getInlineNamespaces() {
|
||||||
return IIndexScope.EMPTY_INDEX_SCOPE_ARRAY;
|
return IIndexScope.EMPTY_INDEX_SCOPE_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFullyInitialized() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,8 @@ Export-Package: org.eclipse.cdt.core,
|
||||||
org.eclipse.cdt.debug.core,
|
org.eclipse.cdt.debug.core,
|
||||||
org.eclipse.cdt.managedbuilder.core,
|
org.eclipse.cdt.managedbuilder.core,
|
||||||
org.eclipse.cdt.make.core,
|
org.eclipse.cdt.make.core,
|
||||||
org.eclipse.cdt.make.ui",
|
org.eclipse.cdt.make.ui,
|
||||||
|
org.eclipse.cdt.codan.core.cxx",
|
||||||
org.eclipse.cdt.internal.core.browser;x-friends:="org.eclipse.cdt.ui",
|
org.eclipse.cdt.internal.core.browser;x-friends:="org.eclipse.cdt.ui",
|
||||||
org.eclipse.cdt.internal.core.cdtvariables;x-internal:=true,
|
org.eclipse.cdt.internal.core.cdtvariables;x-internal:=true,
|
||||||
org.eclipse.cdt.internal.core.dom;x-internal:=true,
|
org.eclipse.cdt.internal.core.dom;x-internal:=true,
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class ScannerDiscoveryLegacySupport {
|
||||||
project = prjDescription.getProject();
|
project = prjDescription.getProject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return isLanguageSettingsProvidersFunctionalityEnabled(project) || isMbsLanguageSettingsProviderOn(cfgDescription);
|
return !isLanguageSettingsProvidersFunctionalityEnabled(project) || isMbsLanguageSettingsProviderOn(cfgDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,7 +130,7 @@ public class ScannerDiscoveryLegacySupport {
|
||||||
if (prjDescription != null) {
|
if (prjDescription != null) {
|
||||||
cfgDescription = prjDescription.getActiveConfiguration();
|
cfgDescription = prjDescription.getActiveConfiguration();
|
||||||
}
|
}
|
||||||
return isLanguageSettingsProvidersFunctionalityEnabled(project) || isMbsLanguageSettingsProviderOn(cfgDescription);
|
return !isLanguageSettingsProvidersFunctionalityEnabled(project) || isMbsLanguageSettingsProviderOn(cfgDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2000, 2011 QNX Software Systems and others.
|
* Copyright (c) 2000, 2012 QNX Software Systems and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -817,6 +817,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTTranslationUnit getAST(IIndex index, int style, IProgressMonitor monitor) throws CoreException {
|
public IASTTranslationUnit getAST(IIndex index, int style, IProgressMonitor monitor) throws CoreException {
|
||||||
|
boolean incompleteIndex = index != null && !index.isFullyInitialized();
|
||||||
IIndexFile[] contextToHeader = getContextToHeader(index, style);
|
IIndexFile[] contextToHeader = getContextToHeader(index, style);
|
||||||
ITranslationUnit configureWith = getConfigureWith(contextToHeader);
|
ITranslationUnit configureWith = getConfigureWith(contextToHeader);
|
||||||
if (configureWith == this)
|
if (configureWith == this)
|
||||||
|
@ -860,6 +861,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
|
||||||
ASTTranslationUnit ast = (ASTTranslationUnit) ((AbstractLanguage) language).getASTTranslationUnit(
|
ASTTranslationUnit ast = (ASTTranslationUnit) ((AbstractLanguage) language).getASTTranslationUnit(
|
||||||
fileContent, scanInfo, crf, index, options, log);
|
fileContent, scanInfo, crf, index, options, log);
|
||||||
ast.setOriginatingTranslationUnit(this);
|
ast.setOriginatingTranslationUnit(this);
|
||||||
|
ast.setBasedOnIncompleteIndex(incompleteIndex);
|
||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2011 IBM Corporation and others.
|
* Copyright (c) 2004, 2012 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -8,6 +8,7 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Doug Schaefer (IBM) - Initial API and implementation
|
* Doug Schaefer (IBM) - Initial API and implementation
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.dom.ast;
|
package org.eclipse.cdt.core.dom.ast;
|
||||||
|
|
||||||
|
@ -347,6 +348,13 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomi
|
||||||
*/
|
*/
|
||||||
public ITranslationUnit getOriginatingTranslationUnit();
|
public ITranslationUnit getOriginatingTranslationUnit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if the index was not fully initialized when the code of the translation
|
||||||
|
* unit was parsed.
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
boolean isBasedOnIncompleteIndex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 5.4
|
* @since 5.4
|
||||||
* @noreference This method is not intended to be referenced by clients.
|
* @noreference This method is not intended to be referenced by clients.
|
||||||
|
|
|
@ -445,4 +445,11 @@ public interface IIndex {
|
||||||
* @since 5.3
|
* @since 5.3
|
||||||
*/
|
*/
|
||||||
public IScope[] getInlineNamespaces() throws CoreException;
|
public IScope[] getInlineNamespaces() throws CoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if the index is fully initialized. An index may not be fully initialized
|
||||||
|
* during Eclipse startup, or soon after adding a new project to the workspace.
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public boolean isFullyInitialized();
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,9 +105,9 @@ public class ASTProblem extends ASTNode implements IASTProblem {
|
||||||
setOffset(startNumber);
|
setOffset(startNumber);
|
||||||
setLength(endNumber-startNumber);
|
setLength(endNumber-startNumber);
|
||||||
|
|
||||||
this.isError= isError;
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.arg = arg;
|
this.arg = arg;
|
||||||
|
this.isError= isError;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ASTProblem(int id, char[] arg, boolean isError) {
|
public ASTProblem(int id, char[] arg, boolean isError) {
|
||||||
|
|
|
@ -80,6 +80,7 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
|
||||||
private SizeofCalculator fSizeofCalculator;
|
private SizeofCalculator fSizeofCalculator;
|
||||||
/** The semaphore controlling exclusive access to the AST. */
|
/** The semaphore controlling exclusive access to the AST. */
|
||||||
private final Semaphore fSemaphore= new Semaphore(1);
|
private final Semaphore fSemaphore= new Semaphore(1);
|
||||||
|
private boolean fBasedOnIncompleteIndex;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final IASTTranslationUnit getTranslationUnit() {
|
public final IASTTranslationUnit getTranslationUnit() {
|
||||||
|
@ -341,6 +342,15 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
|
||||||
fForContentAssist= forContentAssist;
|
fForContentAssist= forContentAssist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBasedOnIncompleteIndex() {
|
||||||
|
return fBasedOnIncompleteIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBasedOnIncompleteIndex(boolean basedOnIncompleteIndex) {
|
||||||
|
fBasedOnIncompleteIndex = basedOnIncompleteIndex;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skippedFile(int offset, InternalFileContent fileContent) {
|
public void skippedFile(int offset, InternalFileContent fileContent) {
|
||||||
if (fIndexFileSet != null) {
|
if (fIndexFileSet != null) {
|
||||||
|
|
|
@ -781,6 +781,15 @@ public class CIndex implements IIndex {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFullyInitialized() {
|
||||||
|
for (IIndexFragment fragment : fFragments) {
|
||||||
|
if (!fragment.isFullyInitialized())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A key used to uniquely identify an IIndexFragmentName object. Uniqueness is guaranteed only
|
* A key used to uniquely identify an IIndexFragmentName object. Uniqueness is guaranteed only
|
||||||
* for names corresponding to the same binding.
|
* for names corresponding to the same binding.
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
* Sergey Prigogin (Google)
|
* Sergey Prigogin (Google)
|
||||||
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
|
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
package org.eclipse.cdt.internal.core.index;
|
package org.eclipse.cdt.internal.core.index;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@ -204,4 +203,9 @@ final public class EmptyCIndex implements IIndex {
|
||||||
public IScope[] getInlineNamespaces() {
|
public IScope[] getInlineNamespaces() {
|
||||||
return new IScope[0];
|
return new IScope[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFullyInitialized() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -349,4 +349,10 @@ public interface IIndexFragment {
|
||||||
* @throws CoreException
|
* @throws CoreException
|
||||||
*/
|
*/
|
||||||
IIndexScope[] getInlineNamespaces() throws CoreException;
|
IIndexScope[] getInlineNamespaces() throws CoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if the index fragment is fully initialized. An fragment may not be fully
|
||||||
|
* initialized during Eclipse startup, or soon after adding a new project to the workspace.
|
||||||
|
*/
|
||||||
|
boolean isFullyInitialized();
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,10 +214,11 @@ public class PDOM extends PlatformObject implements IPDOM {
|
||||||
* 121.0 - Multiple variants of included header file, bug 197989.
|
* 121.0 - Multiple variants of included header file, bug 197989.
|
||||||
* 122.0 - Compacting strings
|
* 122.0 - Compacting strings
|
||||||
* 123.0 - Combined file size and encoding hash code.
|
* 123.0 - Combined file size and encoding hash code.
|
||||||
|
* 124.0 - GCC attributes and NO_RETURN flag for functions.
|
||||||
*/
|
*/
|
||||||
private static final int MIN_SUPPORTED_VERSION= version(123, 0);
|
private static final int MIN_SUPPORTED_VERSION= version(124, 0);
|
||||||
private static final int MAX_SUPPORTED_VERSION= version(123, Short.MAX_VALUE);
|
private static final int MAX_SUPPORTED_VERSION= version(124, Short.MAX_VALUE);
|
||||||
private static final int DEFAULT_VERSION = version(123, 0);
|
private static final int DEFAULT_VERSION = version(124, 0);
|
||||||
|
|
||||||
private static int version(int major, int minor) {
|
private static int version(int major, int minor) {
|
||||||
return (major << 16) + minor;
|
return (major << 16) + minor;
|
||||||
|
@ -1650,4 +1651,9 @@ public class PDOM extends PlatformObject implements IPDOM {
|
||||||
}
|
}
|
||||||
return linkage.getInlineNamespaces();
|
return linkage.getInlineNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFullyInitialized() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -1033,6 +1032,7 @@ public class PDOMManager implements IWritableIndexManager, IListener {
|
||||||
public void handleException(Throwable exception) {
|
public void handleException(Throwable exception) {
|
||||||
CCorePlugin.log(exception);
|
CCorePlugin.log(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
listener.indexChanged(fIndexerStateEvent);
|
listener.indexChanged(fIndexerStateEvent);
|
||||||
|
@ -1070,6 +1070,7 @@ public class PDOMManager implements IWritableIndexManager, IListener {
|
||||||
public void handleException(Throwable exception) {
|
public void handleException(Throwable exception) {
|
||||||
CCorePlugin.log(exception);
|
CCorePlugin.log(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
listener.indexChanged(fIndexChangeEvent);
|
listener.indexChanged(fIndexChangeEvent);
|
||||||
|
@ -1206,42 +1207,41 @@ public class PDOMManager implements IWritableIndexManager, IListener {
|
||||||
if (!deleted) {
|
if (!deleted) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
MessageFormat.format(Messages.PDOMManager_ExistingFileCollides,
|
MessageFormat.format(Messages.PDOMManager_ExistingFileCollides,
|
||||||
new Object[] {targetLocation})
|
targetLocation ));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// copy it
|
// Copy it.
|
||||||
PDOM pdom= getOrCreatePDOM(cproject);
|
PDOM pdom= getOrCreatePDOM(cproject);
|
||||||
pdom.acquireReadLock();
|
pdom.acquireReadLock();
|
||||||
String oldID= null;
|
String oldID= null;
|
||||||
try {
|
try {
|
||||||
oldID= pdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
oldID= pdom.getProperty(IIndexFragment.PROPERTY_FRAGMENT_ID);
|
||||||
pdom.flush();
|
pdom.flush();
|
||||||
FileChannel to = new FileOutputStream(targetLocation).getChannel();
|
FileOutputStream stream = new FileOutputStream(targetLocation);
|
||||||
pdom.getDB().transferTo(to);
|
pdom.getDB().transferTo(stream.getChannel());
|
||||||
to.close();
|
stream.close();
|
||||||
} finally {
|
} finally {
|
||||||
pdom.releaseReadLock();
|
pdom.releaseReadLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// overwrite internal location representations
|
// Overwrite internal location representations.
|
||||||
final WritablePDOM newPDOM = new WritablePDOM(targetLocation, pdom.getLocationConverter(), getLinkageFactories());
|
final WritablePDOM newPDOM = new WritablePDOM(targetLocation, pdom.getLocationConverter(), getLinkageFactories());
|
||||||
newPDOM.acquireWriteLock();
|
newPDOM.acquireWriteLock();
|
||||||
try {
|
try {
|
||||||
newPDOM.rewriteLocations(newConverter);
|
newPDOM.rewriteLocations(newConverter);
|
||||||
|
|
||||||
// ensure fragment id has a sensible value, in case callee's do not
|
// Ensure that fragment id has a sensible value, in case callee's do not
|
||||||
// overwrite their own values
|
// overwrite with their own values.
|
||||||
newPDOM.setProperty(IIndexFragment.PROPERTY_FRAGMENT_ID, "exported." + oldID); //$NON-NLS-1$
|
newPDOM.setProperty(IIndexFragment.PROPERTY_FRAGMENT_ID, "exported." + oldID); //$NON-NLS-1$
|
||||||
newPDOM.close();
|
newPDOM.close();
|
||||||
} finally {
|
} finally {
|
||||||
newPDOM.releaseWriteLock();
|
newPDOM.releaseWriteLock();
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException e) {
|
||||||
throw new CoreException(CCorePlugin.createStatus(ioe.getMessage()));
|
throw new CoreException(CCorePlugin.createStatus(e.getMessage()));
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException e) {
|
||||||
throw new CoreException(CCorePlugin.createStatus(ie.getMessage()));
|
throw new CoreException(CCorePlugin.createStatus(e.getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1440,6 +1440,7 @@ public class PDOMManager implements IWritableIndexManager, IListener {
|
||||||
public void handleException(Throwable exception) {
|
public void handleException(Throwable exception) {
|
||||||
CCorePlugin.log(exception);
|
CCorePlugin.log(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
p.onIndexerSetup(cproject);
|
p.onIndexerSetup(cproject);
|
||||||
|
|
|
@ -350,4 +350,10 @@ public class PDOMProxy implements IPDOM {
|
||||||
|
|
||||||
return IIndexScope.EMPTY_INDEX_SCOPE_ARRAY;
|
return IIndexScope.EMPTY_INDEX_SCOPE_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean isFullyInitialized() {
|
||||||
|
return fDelegate != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
<complexType>
|
<complexType>
|
||||||
<sequence>
|
<sequence>
|
||||||
<element ref="pattern" minOccurs="0" maxOccurs="unbounded"/>
|
<element ref="pattern" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
<element ref="context" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
</sequence>
|
</sequence>
|
||||||
<attribute name="id" type="string">
|
<attribute name="id" type="string">
|
||||||
<annotation>
|
<annotation>
|
||||||
|
@ -147,6 +148,33 @@
|
||||||
</complexType>
|
</complexType>
|
||||||
</element>
|
</element>
|
||||||
|
|
||||||
|
<element name="context">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
Use this element to specify the context where an error parser can be used. If none is specified, a default context type will be "build".
|
||||||
|
|
||||||
|
An error parser can be assigned to more than one context type. For example, an error parser can have two "context" elements, one for "build" and one for "codan".
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
<complexType>
|
||||||
|
<attribute name="type" use="required">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
The type of context where an error parser can be used. Valid values are "build" and "codan".
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
<simpleType>
|
||||||
|
<restriction base="string">
|
||||||
|
<enumeration value="build">
|
||||||
|
</enumeration>
|
||||||
|
<enumeration value="codan">
|
||||||
|
</enumeration>
|
||||||
|
</restriction>
|
||||||
|
</simpleType>
|
||||||
|
</attribute>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
<annotation>
|
<annotation>
|
||||||
<appInfo>
|
<appInfo>
|
||||||
<meta.section type="since"/>
|
<meta.section type="since"/>
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the context in which <code>{@link org.eclipse.cdt.core.IErrorParser}</code>s can be
|
||||||
|
* used.
|
||||||
|
*
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public class ErrorParserContext {
|
||||||
|
public static final int BUILD = 1 << 0;
|
||||||
|
public static final int CODAN = 1 << 1;
|
||||||
|
|
||||||
|
public static int getValue(String text) {
|
||||||
|
if ("build".equals(text)) { //$NON-NLS-1$
|
||||||
|
return BUILD;
|
||||||
|
}
|
||||||
|
if ("codan".equals(text)) { //$NON-NLS-1$
|
||||||
|
return CODAN;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unknown context value: " + text); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,8 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core;
|
package org.eclipse.cdt.core;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.core.ErrorParserContext.BUILD;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -73,9 +75,9 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser,
|
||||||
private final IMarkerGenerator fMarkerGenerator;
|
private final IMarkerGenerator fMarkerGenerator;
|
||||||
|
|
||||||
private Map<String, IErrorParser[]> fErrorParsers;
|
private Map<String, IErrorParser[]> fErrorParsers;
|
||||||
private ArrayList<ProblemMarkerInfo> fErrors;
|
private final ArrayList<ProblemMarkerInfo> fErrors;
|
||||||
|
|
||||||
private Vector<URI> fDirectoryStack;
|
private final Vector<URI> fDirectoryStack;
|
||||||
private final URI fBaseDirectoryURI;
|
private final URI fBaseDirectoryURI;
|
||||||
|
|
||||||
private String previousLine;
|
private String previousLine;
|
||||||
|
@ -147,27 +149,46 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser,
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
public ErrorParserManager(IProject project, URI baseDirectoryURI, IMarkerGenerator markerGenerator, String[] parsersIDs) {
|
public ErrorParserManager(IProject project, URI baseDirectoryURI, IMarkerGenerator markerGenerator, String[] parsersIDs) {
|
||||||
|
this(project, baseDirectoryURI, markerGenerator, parsersIDs, BUILD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URI based constructor.
|
||||||
|
*
|
||||||
|
* @param project - project being built.
|
||||||
|
* @param baseDirectoryURI - absolute location URI of working directory of where the build is performed.
|
||||||
|
* @param markerGenerator - marker generator able to create markers.
|
||||||
|
* @param parsersIDs - array of error parsers' IDs.
|
||||||
|
* @param context - context where the error parser will be used. Valid values are defined by
|
||||||
|
* <code>{@link ErrorParserContext}</code>.
|
||||||
|
* @see ErrorParserContext
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public ErrorParserManager(IProject project, URI baseDirectoryURI,
|
||||||
|
IMarkerGenerator markerGenerator, String[] parsersIDs, int context) {
|
||||||
fProject = project;
|
fProject = project;
|
||||||
fMarkerGenerator = markerGenerator;
|
fMarkerGenerator = markerGenerator;
|
||||||
fDirectoryStack = new Vector<URI>();
|
fDirectoryStack = new Vector<URI>();
|
||||||
fErrors = new ArrayList<ProblemMarkerInfo>();
|
fErrors = new ArrayList<ProblemMarkerInfo>();
|
||||||
enableErrorParsers(parsersIDs);
|
enableErrorParsers(parsersIDs, context);
|
||||||
|
|
||||||
if (baseDirectoryURI != null)
|
if (baseDirectoryURI != null) {
|
||||||
fBaseDirectoryURI = baseDirectoryURI;
|
fBaseDirectoryURI = baseDirectoryURI;
|
||||||
else if (project != null)
|
} else if (project != null) {
|
||||||
fBaseDirectoryURI = project.getLocationURI();
|
fBaseDirectoryURI = project.getLocationURI();
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
fBaseDirectoryURI = org.eclipse.core.filesystem.URIUtil.toURI(System.getProperty("user.dir")); // CWD //$NON-NLS-1$
|
fBaseDirectoryURI = org.eclipse.core.filesystem.URIUtil.toURI(System.getProperty("user.dir")); // CWD //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void enableErrorParsers(String[] parsersIDs) {
|
private void enableErrorParsers(String[] parsersIDs, int context) {
|
||||||
if (parsersIDs == null) {
|
if (parsersIDs == null) {
|
||||||
parsersIDs = ErrorParserExtensionManager.getDefaultErrorParserIds();
|
parsersIDs = ErrorParserExtensionManager.getDefaultErrorParserIds();
|
||||||
}
|
}
|
||||||
fErrorParsers = new LinkedHashMap<String, IErrorParser[]>(parsersIDs.length);
|
fErrorParsers = new LinkedHashMap<String, IErrorParser[]>(parsersIDs.length);
|
||||||
for (String parsersID : parsersIDs) {
|
for (String parsersID : parsersIDs) {
|
||||||
IErrorParser errorParser = getErrorParserCopy(parsersID);
|
IErrorParser errorParser = getErrorParserCopy(parsersID, context);
|
||||||
if (errorParser!=null) {
|
if (errorParser!=null) {
|
||||||
fErrorParsers.put(parsersID, new IErrorParser[] {errorParser} );
|
fErrorParsers.put(parsersID, new IErrorParser[] {errorParser} );
|
||||||
}
|
}
|
||||||
|
@ -196,8 +217,9 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser,
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public URI getWorkingDirectoryURI() {
|
public URI getWorkingDirectoryURI() {
|
||||||
if (!fDirectoryStack.isEmpty())
|
if (!fDirectoryStack.isEmpty()) {
|
||||||
return fDirectoryStack.lastElement();
|
return fDirectoryStack.lastElement();
|
||||||
|
}
|
||||||
|
|
||||||
// Fall back to the Project Location / Build directory
|
// Fall back to the Project Location / Build directory
|
||||||
return fBaseDirectoryURI;
|
return fBaseDirectoryURI;
|
||||||
|
@ -214,13 +236,14 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser,
|
||||||
if (dir != null) {
|
if (dir != null) {
|
||||||
URI uri;
|
URI uri;
|
||||||
URI workingDirectoryURI = getWorkingDirectoryURI();
|
URI workingDirectoryURI = getWorkingDirectoryURI();
|
||||||
if (!dir.isAbsolute())
|
if (!dir.isAbsolute()) {
|
||||||
uri = URIUtil.append(workingDirectoryURI, dir.toString());
|
uri = URIUtil.append(workingDirectoryURI, dir.toString());
|
||||||
else {
|
} else {
|
||||||
uri = toURI(dir);
|
uri = toURI(dir);
|
||||||
if (uri == null) // Shouldn't happen; error logged
|
if (uri == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pushDirectoryURI(uri);
|
pushDirectoryURI(uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,12 +258,13 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser,
|
||||||
*/
|
*/
|
||||||
public void pushDirectoryURI(URI dir) {
|
public void pushDirectoryURI(URI dir) {
|
||||||
if (dir != null) {
|
if (dir != null) {
|
||||||
if (dir.isAbsolute())
|
if (dir.isAbsolute()) {
|
||||||
fDirectoryStack.addElement(dir);
|
fDirectoryStack.addElement(dir);
|
||||||
else
|
} else {
|
||||||
fDirectoryStack.addElement(URIUtil.makeAbsolute(dir, getWorkingDirectoryURI()));
|
fDirectoryStack.addElement(URIUtil.makeAbsolute(dir, getWorkingDirectoryURI()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link #pushDirectory} and {@link #popDirectory} are used to change working directory
|
* {@link #pushDirectory} and {@link #popDirectory} are used to change working directory
|
||||||
|
@ -331,9 +355,10 @@ outer:
|
||||||
}
|
}
|
||||||
if ((types & IErrorParser2.KEEP_LONGLINES) == 0) {
|
if ((types & IErrorParser2.KEEP_LONGLINES) == 0) {
|
||||||
// long lines are not given to parsers, unless it wants it
|
// long lines are not given to parsers, unless it wants it
|
||||||
if (lineTrimmed.length() > 1000)
|
if (lineTrimmed.length() > 1000) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// standard behavior (pre 5.1) is to trim the line
|
// standard behavior (pre 5.1) is to trim the line
|
||||||
String lineToParse = lineTrimmed;
|
String lineToParse = lineTrimmed;
|
||||||
if ((types & IErrorParser2.KEEP_UNTRIMMED) !=0 ) {
|
if ((types & IErrorParser2.KEEP_UNTRIMMED) !=0 ) {
|
||||||
|
@ -349,23 +374,26 @@ outer:
|
||||||
consume = curr.processLine(lineToParse, this);
|
consume = curr.processLine(lineToParse, this);
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
String id = ""; //$NON-NLS-1$
|
String id = ""; //$NON-NLS-1$
|
||||||
if (parser instanceof IErrorParserNamed)
|
if (parser instanceof IErrorParserNamed) {
|
||||||
id = ((IErrorParserNamed)parser).getId();
|
id = ((IErrorParserNamed)parser).getId();
|
||||||
|
}
|
||||||
@SuppressWarnings("nls")
|
@SuppressWarnings("nls")
|
||||||
String message = "Errorparser " + id + " failed parsing line [" + lineToParse + "]";
|
String message = "Errorparser " + id + " failed parsing line [" + lineToParse + "]";
|
||||||
CCorePlugin.log(message, e);
|
CCorePlugin.log(message, e);
|
||||||
} finally {
|
} finally {
|
||||||
if (fErrors.size() > 0) {
|
if (fErrors.size() > 0) {
|
||||||
if (marker==null)
|
if (marker==null) {
|
||||||
marker = fErrors.get(0);
|
marker = fErrors.get(0);
|
||||||
|
}
|
||||||
fErrors.clear();
|
fErrors.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (consume)
|
if (consume) {
|
||||||
break outer;
|
break outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
outputLine(line, marker);
|
outputLine(line, marker);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -377,7 +405,9 @@ outer:
|
||||||
*/
|
*/
|
||||||
private void outputLine(String line, ProblemMarkerInfo marker) {
|
private void outputLine(String line, ProblemMarkerInfo marker) {
|
||||||
String l = line + "\n"; //$NON-NLS-1$
|
String l = line + "\n"; //$NON-NLS-1$
|
||||||
if ( outputStream == null ) return;
|
if ( outputStream == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if ( marker != null && outputStream instanceof IErrorMarkeredOutputStream ) {
|
if ( marker != null && outputStream instanceof IErrorMarkeredOutputStream ) {
|
||||||
IErrorMarkeredOutputStream s = (IErrorMarkeredOutputStream) outputStream;
|
IErrorMarkeredOutputStream s = (IErrorMarkeredOutputStream) outputStream;
|
||||||
|
@ -417,8 +447,9 @@ outer:
|
||||||
*/
|
*/
|
||||||
public IFile findFileName(String partialLoc) {
|
public IFile findFileName(String partialLoc) {
|
||||||
if (partialLoc.equals(cachedFileName) && cachedWorkingDirectory != null &&
|
if (partialLoc.equals(cachedFileName) && cachedWorkingDirectory != null &&
|
||||||
org.eclipse.core.filesystem.URIUtil.equals(getWorkingDirectoryURI(), cachedWorkingDirectory))
|
org.eclipse.core.filesystem.URIUtil.equals(getWorkingDirectoryURI(), cachedWorkingDirectory)) {
|
||||||
return cachedFile;
|
return cachedFile;
|
||||||
|
}
|
||||||
|
|
||||||
// To be able to parse Windows paths on Linux systems, see bug 263977
|
// To be able to parse Windows paths on Linux systems, see bug 263977
|
||||||
IPath path = new Path(partialLoc.replace('\\', IPath.SEPARATOR));
|
IPath path = new Path(partialLoc.replace('\\', IPath.SEPARATOR));
|
||||||
|
@ -433,18 +464,21 @@ outer:
|
||||||
if (fProject != null) {
|
if (fProject != null) {
|
||||||
IProject[] prjs = new IProject[] { fProject };
|
IProject[] prjs = new IProject[] { fProject };
|
||||||
files = ResourceLookup.findFilesByName(path, prjs, false);
|
files = ResourceLookup.findFilesByName(path, prjs, false);
|
||||||
if (files.length == 0)
|
if (files.length == 0) {
|
||||||
files = ResourceLookup.findFilesByName(path, prjs, /* ignoreCase */ true);
|
files = ResourceLookup.findFilesByName(path, prjs, /* ignoreCase */ true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (files == null || files.length == 0) {
|
if (files == null || files.length == 0) {
|
||||||
IProject[] prjs = ResourcesPlugin.getWorkspace().getRoot().getProjects();
|
IProject[] prjs = ResourcesPlugin.getWorkspace().getRoot().getProjects();
|
||||||
files = ResourceLookup.findFilesByName(path, prjs, false);
|
files = ResourceLookup.findFilesByName(path, prjs, false);
|
||||||
if (files.length == 0)
|
if (files.length == 0) {
|
||||||
files = ResourceLookup.findFilesByName(path, prjs, /* ignoreCase */ true);
|
files = ResourceLookup.findFilesByName(path, prjs, /* ignoreCase */ true);
|
||||||
}
|
}
|
||||||
if (files.length == 1)
|
}
|
||||||
|
if (files.length == 1) {
|
||||||
file = files[0];
|
file = files[0];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Could be cygwin path
|
// Could be cygwin path
|
||||||
if (file==null && isCygwin && path.isAbsolute()) {
|
if (file==null && isCygwin && path.isAbsolute()) {
|
||||||
|
@ -471,9 +505,10 @@ outer:
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uri = toURI(path);
|
uri = toURI(path);
|
||||||
if (uri == null) // Shouldn't happen; error logged
|
if (uri == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return findFileInWorkspace(uri);
|
return findFileInWorkspace(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,12 +520,14 @@ outer:
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
protected IFile findFileInWorkspace(URI uri) {
|
protected IFile findFileInWorkspace(URI uri) {
|
||||||
if (!uri.isAbsolute())
|
if (!uri.isAbsolute()) {
|
||||||
uri = URIUtil.makeAbsolute(uri, getWorkingDirectoryURI());
|
uri = URIUtil.makeAbsolute(uri, getWorkingDirectoryURI());
|
||||||
|
}
|
||||||
|
|
||||||
IFile f = ResourceLookup.selectFileForLocationURI(uri, fProject);
|
IFile f = ResourceLookup.selectFileForLocationURI(uri, fProject);
|
||||||
if (f != null && f.isAccessible())
|
if (f != null && f.isAccessible()) {
|
||||||
return f;
|
return f;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,9 +618,10 @@ outer:
|
||||||
public void addProblemMarker(ProblemMarkerInfo problemMarkerInfo){
|
public void addProblemMarker(ProblemMarkerInfo problemMarkerInfo){
|
||||||
fErrors.add(problemMarkerInfo);
|
fErrors.add(problemMarkerInfo);
|
||||||
fMarkerGenerator.addMarker(problemMarkerInfo);
|
fMarkerGenerator.addMarker(problemMarkerInfo);
|
||||||
if (problemMarkerInfo.severity == IMarkerGenerator.SEVERITY_ERROR_RESOURCE)
|
if (problemMarkerInfo.severity == IMarkerGenerator.SEVERITY_ERROR_RESOURCE) {
|
||||||
hasErrors = true;
|
hasErrors = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the error parsers.
|
* Called by the error parsers.
|
||||||
|
@ -632,9 +670,10 @@ outer:
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void flush() throws IOException {
|
public void flush() throws IOException {
|
||||||
if (outputStream != null)
|
if (outputStream != null) {
|
||||||
outputStream.flush();
|
outputStream.flush();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see java.io.OutputStream#write(int)
|
* @see java.io.OutputStream#write(int)
|
||||||
|
@ -668,8 +707,9 @@ outer:
|
||||||
while ((i = buffer.indexOf('\n')) != -1) {
|
while ((i = buffer.indexOf('\n')) != -1) {
|
||||||
String line = buffer.substring(0, i);
|
String line = buffer.substring(0, i);
|
||||||
// get rid of any trailing '\r'
|
// get rid of any trailing '\r'
|
||||||
if (line.endsWith("\r")) //$NON-NLS-1$
|
if (line.endsWith("\r")) { //$NON-NLS-1$
|
||||||
line=line.substring(0,line.length()-1);
|
line=line.substring(0,line.length()-1);
|
||||||
|
}
|
||||||
processLine(line);
|
processLine(line);
|
||||||
previousLine = line;
|
previousLine = line;
|
||||||
buffer = buffer.substring(i + 1); // skip the \n and advance
|
buffer = buffer.substring(i + 1); // skip the \n and advance
|
||||||
|
@ -718,8 +758,9 @@ outer:
|
||||||
String uriString = path.toString();
|
String uriString = path.toString();
|
||||||
|
|
||||||
// On Windows "C:/folder/" -> "/C:/folder/"
|
// On Windows "C:/folder/" -> "/C:/folder/"
|
||||||
if (path.isAbsolute() && uriString.charAt(0) != IPath.SEPARATOR)
|
if (path.isAbsolute() && uriString.charAt(0) != IPath.SEPARATOR) {
|
||||||
uriString = IPath.SEPARATOR + uriString;
|
uriString = IPath.SEPARATOR + uriString;
|
||||||
|
}
|
||||||
|
|
||||||
return EFSExtensionManager.getDefault().createNewURIFromPath(baseURI, uriString);
|
return EFSExtensionManager.getDefault().createNewURIFromPath(baseURI, uriString);
|
||||||
}
|
}
|
||||||
|
@ -829,6 +870,20 @@ outer:
|
||||||
return ErrorParserExtensionManager.getErrorParserCopy(id, false);
|
return ErrorParserExtensionManager.getErrorParserCopy(id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id - ID of error parser
|
||||||
|
* @param context - context where the error parser will be used. Valid values are defined by
|
||||||
|
* <code>{@link ErrorParserContext}</code>.
|
||||||
|
* @return cloned copy of error parser or {@code null}.
|
||||||
|
* Note that {@link ErrorParserNamedWrapper} returns shallow copy with the same instance
|
||||||
|
* of underlying error parser.
|
||||||
|
* @see ErrorParserContext
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public static IErrorParserNamed getErrorParserCopy(String id, int context) {
|
||||||
|
return ErrorParserExtensionManager.getErrorParserCopy(id, false, context);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id - ID of error parser
|
* @param id - ID of error parser
|
||||||
* @return cloned copy of error parser as defined by its extension point or {@code null}.
|
* @return cloned copy of error parser as defined by its extension point or {@code null}.
|
||||||
|
@ -860,5 +915,12 @@ outer:
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
for (IErrorParser[] parsers : fErrorParsers.values()) {
|
||||||
|
for (IErrorParser parser : parsers) {
|
||||||
|
if (parser instanceof IErrorParser3) {
|
||||||
|
((IErrorParser3) parser).streamFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public interface IErrorParser3 extends IErrorParser2 {
|
||||||
|
/**
|
||||||
|
* Notification that the stream of data to parse has ended.
|
||||||
|
*/
|
||||||
|
void streamFinished();
|
||||||
|
}
|
|
@ -35,6 +35,14 @@ public class ProblemMarkerInfo {
|
||||||
|
|
||||||
public IResource file;
|
public IResource file;
|
||||||
public int lineNumber;
|
public int lineNumber;
|
||||||
|
/**
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public int startChar;
|
||||||
|
/**
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public int endChar;
|
||||||
public String description;
|
public String description;
|
||||||
public int severity;
|
public int severity;
|
||||||
public String variableName;
|
public String variableName;
|
||||||
|
@ -53,6 +61,24 @@ public class ProblemMarkerInfo {
|
||||||
* @param variableName - the name of the variable involved in the error if any.
|
* @param variableName - the name of the variable involved in the error if any.
|
||||||
*/
|
*/
|
||||||
public ProblemMarkerInfo(IResource file, int lineNumber, String description, int severity, String variableName) {
|
public ProblemMarkerInfo(IResource file, int lineNumber, String description, int severity, String variableName) {
|
||||||
|
this(file, lineNumber, -1,-1, description, severity, variableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link ProblemMarkerInfo} object.
|
||||||
|
*
|
||||||
|
* @param file - the file where the problem has occurred.
|
||||||
|
* @param lineNumber - the line number of the problem.
|
||||||
|
* @param startChar - start char of the problem.
|
||||||
|
* @param endChar - end char of the problem.
|
||||||
|
* @param description - a description of the problem.
|
||||||
|
* @param severity - the severity of the problem, see {@link IMarkerGenerator}
|
||||||
|
* for acceptable severity values.
|
||||||
|
* @param variableName - the name of the variable involved in the error if any.
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public ProblemMarkerInfo(IResource file, int lineNumber, int startChar, int endChar,
|
||||||
|
String description, int severity, String variableName) {
|
||||||
this.file = (file != null) ? file : ResourcesPlugin.getWorkspace().getRoot();
|
this.file = (file != null) ? file : ResourcesPlugin.getWorkspace().getRoot();
|
||||||
this.lineNumber = lineNumber;
|
this.lineNumber = lineNumber;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
|
@ -61,6 +87,8 @@ public class ProblemMarkerInfo {
|
||||||
this.externalPath = null ;
|
this.externalPath = null ;
|
||||||
this.type = null;
|
this.type = null;
|
||||||
this.attributes = new HashMap<String, String>();
|
this.attributes = new HashMap<String, String>();
|
||||||
|
this.startChar = -1;
|
||||||
|
this.endChar = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,24 +11,29 @@
|
||||||
|
|
||||||
package org.eclipse.cdt.internal.errorparsers;
|
package org.eclipse.cdt.internal.errorparsers;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.core.ErrorParserContext.BUILD;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.ErrorParserManager;
|
import org.eclipse.cdt.core.ErrorParserManager;
|
||||||
|
import org.eclipse.cdt.core.ErrorParserContext;
|
||||||
import org.eclipse.cdt.core.IErrorParser;
|
import org.eclipse.cdt.core.IErrorParser;
|
||||||
import org.eclipse.cdt.core.IErrorParserNamed;
|
import org.eclipse.cdt.core.IErrorParserNamed;
|
||||||
import org.eclipse.cdt.core.IMarkerGenerator;
|
import org.eclipse.cdt.core.IMarkerGenerator;
|
||||||
import org.eclipse.cdt.core.errorparsers.ErrorParserNamedWrapper;
|
import org.eclipse.cdt.core.errorparsers.ErrorParserNamedWrapper;
|
||||||
import org.eclipse.cdt.core.errorparsers.RegexErrorParser;
|
import org.eclipse.cdt.core.errorparsers.RegexErrorParser;
|
||||||
import org.eclipse.cdt.core.errorparsers.RegexErrorPattern;
|
import org.eclipse.cdt.core.errorparsers.RegexErrorPattern;
|
||||||
|
import org.eclipse.cdt.internal.core.Pair;
|
||||||
import org.eclipse.cdt.internal.core.XmlUtil;
|
import org.eclipse.cdt.internal.core.XmlUtil;
|
||||||
import org.eclipse.core.filesystem.URIUtil;
|
import org.eclipse.core.filesystem.URIUtil;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
@ -56,6 +61,7 @@ public class ErrorParserExtensionManager {
|
||||||
private static final String NONE = ""; //$NON-NLS-1$
|
private static final String NONE = ""; //$NON-NLS-1$
|
||||||
|
|
||||||
private static final String EXTENSION_POINT_ERROR_PARSER = "org.eclipse.cdt.core.ErrorParser"; //$NON-NLS-1$
|
private static final String EXTENSION_POINT_ERROR_PARSER = "org.eclipse.cdt.core.ErrorParser"; //$NON-NLS-1$
|
||||||
|
private static final String ELEM_CONTEXT = "context"; //$NON-NLS-1$
|
||||||
private static final String ELEM_PLUGIN = "plugin"; //$NON-NLS-1$
|
private static final String ELEM_PLUGIN = "plugin"; //$NON-NLS-1$
|
||||||
private static final String ELEM_EXTENSION = "extension"; //$NON-NLS-1$
|
private static final String ELEM_EXTENSION = "extension"; //$NON-NLS-1$
|
||||||
private static final String ELEM_ERRORPARSER = "errorparser"; //$NON-NLS-1$
|
private static final String ELEM_ERRORPARSER = "errorparser"; //$NON-NLS-1$
|
||||||
|
@ -64,6 +70,8 @@ public class ErrorParserExtensionManager {
|
||||||
private static final String ATTR_ID = "id"; //$NON-NLS-1$
|
private static final String ATTR_ID = "id"; //$NON-NLS-1$
|
||||||
private static final String ATTR_NAME = "name"; //$NON-NLS-1$
|
private static final String ATTR_NAME = "name"; //$NON-NLS-1$
|
||||||
private static final String ATTR_POINT = "point"; //$NON-NLS-1$
|
private static final String ATTR_POINT = "point"; //$NON-NLS-1$
|
||||||
|
private static final String ATTR_TYPE = "type"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
|
||||||
private static final String ATTR_REGEX = "regex"; //$NON-NLS-1$
|
private static final String ATTR_REGEX = "regex"; //$NON-NLS-1$
|
||||||
private static final String ATTR_SEVERITY = "severity"; //$NON-NLS-1$
|
private static final String ATTR_SEVERITY = "severity"; //$NON-NLS-1$
|
||||||
|
@ -78,8 +86,10 @@ public class ErrorParserExtensionManager {
|
||||||
private static final String ATTR_VALUE_INFO = "Info"; //$NON-NLS-1$
|
private static final String ATTR_VALUE_INFO = "Info"; //$NON-NLS-1$
|
||||||
private static final String ATTR_VALUE_IGNORE = "Ignore"; //$NON-NLS-1$
|
private static final String ATTR_VALUE_IGNORE = "Ignore"; //$NON-NLS-1$
|
||||||
|
|
||||||
private static final LinkedHashMap<String, IErrorParserNamed> fExtensionErrorParsers = new LinkedHashMap<String, IErrorParserNamed>();
|
// Key: error parser id. Value: pair of error parser and contexts value
|
||||||
private static final LinkedHashMap<String, IErrorParserNamed> fAvailableErrorParsers = new LinkedHashMap<String, IErrorParserNamed>();
|
private static final LinkedHashMap<String, Pair<IErrorParserNamed, Integer>> fExtensionErrorParsers = new LinkedHashMap<String, Pair<IErrorParserNamed, Integer>>();
|
||||||
|
// Key: error parser id. Value: pair of error parser and contexts value
|
||||||
|
private static final LinkedHashMap<String, Pair<IErrorParserNamed, Integer>> fAvailableErrorParsers = new LinkedHashMap<String, Pair<IErrorParserNamed, Integer>>();
|
||||||
private static LinkedHashMap<String, IErrorParserNamed> fUserDefinedErrorParsers = null;
|
private static LinkedHashMap<String, IErrorParserNamed> fUserDefinedErrorParsers = null;
|
||||||
private static List<String> fDefaultErrorParserIds = null;
|
private static List<String> fDefaultErrorParserIds = null;
|
||||||
|
|
||||||
|
@ -112,6 +122,18 @@ public class ErrorParserExtensionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ErrorParserAndContextComparator implements Comparator<Pair<IErrorParserNamed, Integer>> {
|
||||||
|
private static final ErrorParserComparator DELEGATE = new ErrorParserComparator();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(Pair<IErrorParserNamed, Integer> pair1,
|
||||||
|
Pair<IErrorParserNamed, Integer> pair2) {
|
||||||
|
IErrorParserNamed parser1 = pair1.first;
|
||||||
|
IErrorParserNamed parser2 = pair2.first;
|
||||||
|
return DELEGATE.compare(parser1, parser2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
loadUserDefinedErrorParsers();
|
loadUserDefinedErrorParsers();
|
||||||
loadDefaultErrorParserIds();
|
loadDefaultErrorParserIds();
|
||||||
|
@ -202,12 +224,13 @@ public class ErrorParserExtensionManager {
|
||||||
* @noreference This method is not intended to be referenced by clients.
|
* @noreference This method is not intended to be referenced by clients.
|
||||||
*/
|
*/
|
||||||
synchronized public static void loadErrorParserExtensions() {
|
synchronized public static void loadErrorParserExtensions() {
|
||||||
Set<IErrorParserNamed> sortedErrorParsers = new TreeSet<IErrorParserNamed>(new ErrorParserComparator());
|
Set<Pair<IErrorParserNamed, Integer>> sortedErrorParsers =
|
||||||
|
new TreeSet<Pair<IErrorParserNamed, Integer>>(new ErrorParserAndContextComparator());
|
||||||
loadErrorParserExtensions(Platform.getExtensionRegistry(), sortedErrorParsers);
|
loadErrorParserExtensions(Platform.getExtensionRegistry(), sortedErrorParsers);
|
||||||
|
|
||||||
fExtensionErrorParsers.clear();
|
fExtensionErrorParsers.clear();
|
||||||
for (IErrorParserNamed errorParser : sortedErrorParsers) {
|
for (Pair<IErrorParserNamed, Integer> pair : sortedErrorParsers) {
|
||||||
fExtensionErrorParsers.put(errorParser.getId(), errorParser);
|
fExtensionErrorParsers.put(pair.first.getId(), pair);
|
||||||
}
|
}
|
||||||
recalculateAvailableErrorParsers();
|
recalculateAvailableErrorParsers();
|
||||||
}
|
}
|
||||||
|
@ -218,7 +241,8 @@ public class ErrorParserExtensionManager {
|
||||||
* @param registry - extension registry
|
* @param registry - extension registry
|
||||||
* @param errorParsers - resulting set of error parsers
|
* @param errorParsers - resulting set of error parsers
|
||||||
*/
|
*/
|
||||||
private static void loadErrorParserExtensions(IExtensionRegistry registry, Set<IErrorParserNamed> errorParsers) {
|
private static void loadErrorParserExtensions(IExtensionRegistry registry,
|
||||||
|
Set<Pair<IErrorParserNamed, Integer>> errorParsers) {
|
||||||
errorParsers.clear();
|
errorParsers.clear();
|
||||||
IExtensionPoint extension = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID, CCorePlugin.ERROR_PARSER_SIMPLE_ID);
|
IExtensionPoint extension = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID, CCorePlugin.ERROR_PARSER_SIMPLE_ID);
|
||||||
if (extension != null) {
|
if (extension != null) {
|
||||||
|
@ -232,8 +256,9 @@ public class ErrorParserExtensionManager {
|
||||||
if (cfgEl.getName().equals(ELEM_ERRORPARSER)) {
|
if (cfgEl.getName().equals(ELEM_ERRORPARSER)) {
|
||||||
IErrorParserNamed errorParser = createErrorParserCarcass(oldStyleId, oldStyleName, cfgEl);
|
IErrorParserNamed errorParser = createErrorParserCarcass(oldStyleId, oldStyleName, cfgEl);
|
||||||
if (errorParser!=null) {
|
if (errorParser!=null) {
|
||||||
|
Pair<IErrorParserNamed, Integer> configured =
|
||||||
configureErrorParser(errorParser, cfgEl);
|
configureErrorParser(errorParser, cfgEl);
|
||||||
errorParsers.add(errorParser);
|
errorParsers.add(configured);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,42 +279,50 @@ public class ErrorParserExtensionManager {
|
||||||
List<String> ids = new ArrayList<String>();
|
List<String> ids = new ArrayList<String>();
|
||||||
if (fDefaultErrorParserIds!=null) {
|
if (fDefaultErrorParserIds!=null) {
|
||||||
for (String id : fDefaultErrorParserIds) {
|
for (String id : fDefaultErrorParserIds) {
|
||||||
|
Pair<IErrorParserNamed, Integer> pair = null;
|
||||||
IErrorParserNamed errorParser = null;
|
IErrorParserNamed errorParser = null;
|
||||||
if (fUserDefinedErrorParsers!=null) {
|
if (fUserDefinedErrorParsers!=null) {
|
||||||
errorParser = fUserDefinedErrorParsers.get(id);
|
errorParser = fUserDefinedErrorParsers.get(id);
|
||||||
}
|
}
|
||||||
if (errorParser==null) {
|
|
||||||
errorParser = fExtensionErrorParsers.get(id);
|
|
||||||
}
|
|
||||||
if (errorParser != null) {
|
if (errorParser != null) {
|
||||||
fAvailableErrorParsers.put(id, errorParser);
|
pair = errorParserForBuild(errorParser);
|
||||||
|
} else {
|
||||||
|
pair = fExtensionErrorParsers.get(id);
|
||||||
|
}
|
||||||
|
if (pair != null) {
|
||||||
|
fAvailableErrorParsers.put(id, pair);
|
||||||
ids.add(id);
|
ids.add(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// then the rest in the order defined by comparator
|
// then the rest in the order defined by comparator
|
||||||
Set<IErrorParserNamed> sortedErrorParsers = new TreeSet<IErrorParserNamed>(new ErrorParserComparator());
|
Set<Pair<IErrorParserNamed, Integer>> sortedErrorParsers =
|
||||||
|
new TreeSet<Pair<IErrorParserNamed, Integer>>(new ErrorParserAndContextComparator());
|
||||||
|
|
||||||
if (fUserDefinedErrorParsers!=null) {
|
if (fUserDefinedErrorParsers!=null) {
|
||||||
for (String id : fUserDefinedErrorParsers.keySet()) {
|
for (String id : fUserDefinedErrorParsers.keySet()) {
|
||||||
if (!ids.contains(id)) {
|
if (!ids.contains(id)) {
|
||||||
IErrorParserNamed errorParser = fUserDefinedErrorParsers.get(id);
|
IErrorParserNamed errorParser = fUserDefinedErrorParsers.get(id);
|
||||||
sortedErrorParsers.add(errorParser);
|
sortedErrorParsers.add(errorParserForBuild(errorParser));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (String id : fExtensionErrorParsers.keySet()) {
|
for (String id : fExtensionErrorParsers.keySet()) {
|
||||||
if (!ids.contains(id)) {
|
if (!ids.contains(id)) {
|
||||||
IErrorParserNamed errorParser = fExtensionErrorParsers.get(id);
|
Pair<IErrorParserNamed, Integer> pair = fExtensionErrorParsers.get(id);
|
||||||
sortedErrorParsers.add(errorParser);
|
sortedErrorParsers.add(pair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IErrorParserNamed errorParser : sortedErrorParsers) {
|
for (Pair<IErrorParserNamed, Integer> pairs : sortedErrorParsers) {
|
||||||
fAvailableErrorParsers.put(errorParser.getId(), errorParser);
|
fAvailableErrorParsers.put(pairs.first.getId(), pairs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Pair<IErrorParserNamed, Integer> errorParserForBuild(IErrorParserNamed errorParser) {
|
||||||
|
return new Pair<IErrorParserNamed, Integer>(errorParser, ErrorParserContext.BUILD);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize error parsers in workspace level storage.
|
* Serialize error parsers in workspace level storage.
|
||||||
*
|
*
|
||||||
|
@ -544,7 +577,8 @@ public class ErrorParserExtensionManager {
|
||||||
* @param cfgEl - extension configuration element
|
* @param cfgEl - extension configuration element
|
||||||
* @throws CoreException
|
* @throws CoreException
|
||||||
*/
|
*/
|
||||||
private static void configureErrorParser(IErrorParserNamed errorParser, IConfigurationElement cfgEl) throws CoreException {
|
private static Pair<IErrorParserNamed, Integer> configureErrorParser(
|
||||||
|
IErrorParserNamed errorParser, IConfigurationElement cfgEl) throws CoreException {
|
||||||
String id = cfgEl.getAttribute(ATTR_ID);
|
String id = cfgEl.getAttribute(ATTR_ID);
|
||||||
if (id!=null && id.length()>0)
|
if (id!=null && id.length()>0)
|
||||||
errorParser.setId(id);
|
errorParser.setId(id);
|
||||||
|
@ -569,6 +603,31 @@ public class ErrorParserExtensionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int contexts = contextTypes(cfgEl);
|
||||||
|
return new Pair<IErrorParserNamed, Integer>(errorParser, contexts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a bit mask of contexts where an error parser can be used. Valid values for context
|
||||||
|
* are defined in <code>{@link ErrorParserContext}</code>.
|
||||||
|
*
|
||||||
|
* @param errorParserElement represents an "errorparser" element in the extension point
|
||||||
|
* "org.eclipse.cdt.core.ErrorParser".
|
||||||
|
* @return the contexts in which an error parser can be used, or
|
||||||
|
* <code>{@link ErrorParserContext#BUILD BUILD}</code> is none is specified.
|
||||||
|
* @see ErrorParserContext
|
||||||
|
*/
|
||||||
|
private static int contextTypes(IConfigurationElement errorParserElement) {
|
||||||
|
IConfigurationElement[] contextElements = errorParserElement.getChildren(ELEM_CONTEXT);
|
||||||
|
if (contextElements.length == 0) {
|
||||||
|
return BUILD;
|
||||||
|
}
|
||||||
|
int contexts = 0;
|
||||||
|
for (IConfigurationElement contextElement : contextElements) {
|
||||||
|
String contextType = contextElement.getAttribute(ATTR_TYPE);
|
||||||
|
contexts = contexts | ErrorParserContext.getValue(contextType);
|
||||||
|
}
|
||||||
|
return contexts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -581,7 +640,8 @@ public class ErrorParserExtensionManager {
|
||||||
* @return internal instance of error parser
|
* @return internal instance of error parser
|
||||||
*/
|
*/
|
||||||
public static IErrorParser getErrorParserInternal(String id) {
|
public static IErrorParser getErrorParserInternal(String id) {
|
||||||
IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);
|
Pair<IErrorParserNamed, Integer> pair = fAvailableErrorParsers.get(id);
|
||||||
|
IErrorParserNamed errorParser = pair.first;
|
||||||
if (errorParser instanceof ErrorParserNamedWrapper)
|
if (errorParser instanceof ErrorParserNamedWrapper)
|
||||||
return ((ErrorParserNamedWrapper)errorParser).getErrorParser();
|
return ((ErrorParserNamedWrapper)errorParser).getErrorParser();
|
||||||
return errorParser;
|
return errorParser;
|
||||||
|
@ -626,14 +686,25 @@ public class ErrorParserExtensionManager {
|
||||||
* from workspace
|
* from workspace
|
||||||
*/
|
*/
|
||||||
public static String[] getErrorParserAvailableIds() {
|
public static String[] getErrorParserAvailableIds() {
|
||||||
return fAvailableErrorParsers.keySet().toArray(new String[0]);
|
return getErrorParserIds(fAvailableErrorParsers, BUILD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return IDs of error parsers contributed through error parser extension point.
|
* @return IDs of error parsers contributed through error parser extension point.
|
||||||
*/
|
*/
|
||||||
public static String[] getErrorParserExtensionIds() {
|
public static String[] getErrorParserExtensionIds() {
|
||||||
return fExtensionErrorParsers.keySet().toArray(new String[0]);
|
return getErrorParserIds(fExtensionErrorParsers, BUILD);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] getErrorParserIds(
|
||||||
|
Map<String, Pair<IErrorParserNamed, Integer>> parsers, int context) {
|
||||||
|
List<String> ids = new ArrayList<String>();
|
||||||
|
for (Map.Entry<String, Pair<IErrorParserNamed, Integer>> entry : parsers.entrySet()) {
|
||||||
|
if (isInContext(entry.getValue(), context)) {
|
||||||
|
ids.add(entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ids.toArray(new String[ids.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -690,8 +761,26 @@ public class ErrorParserExtensionManager {
|
||||||
* shallow copy with the same instance of underlying error parser.
|
* shallow copy with the same instance of underlying error parser.
|
||||||
*/
|
*/
|
||||||
public static IErrorParserNamed getErrorParserCopy(String id, boolean isExtension) {
|
public static IErrorParserNamed getErrorParserCopy(String id, boolean isExtension) {
|
||||||
IErrorParserNamed errorParser = isExtension ? fExtensionErrorParsers.get(id) : fAvailableErrorParsers.get(id);
|
return getErrorParserCopy(id, isExtension, BUILD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id - ID of error parser
|
||||||
|
* @param isExtension - if {@code true} get unmodified copy of error parser defined as extension
|
||||||
|
* @param context - context where the error parser will be used. Valid values are defined by
|
||||||
|
* <code>{@link ErrorParserContext}</code>.
|
||||||
|
* @return cloned copy of error parser. Note that {@link ErrorParserNamedWrapper} returns
|
||||||
|
* shallow copy with the same instance of underlying error parser.
|
||||||
|
* @see ErrorParserContext
|
||||||
|
*/
|
||||||
|
public static IErrorParserNamed getErrorParserCopy(String id, boolean isExtension,
|
||||||
|
int context) {
|
||||||
|
Pair<IErrorParserNamed, Integer> pair =
|
||||||
|
isExtension ? fExtensionErrorParsers.get(id) : fAvailableErrorParsers.get(id);
|
||||||
|
if (!isInContext(pair, context)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
IErrorParserNamed errorParser = pair.first;
|
||||||
try {
|
try {
|
||||||
if (errorParser instanceof RegexErrorParser) {
|
if (errorParser instanceof RegexErrorParser) {
|
||||||
return (RegexErrorParser) ((RegexErrorParser)errorParser).clone();
|
return (RegexErrorParser) ((RegexErrorParser)errorParser).clone();
|
||||||
|
@ -704,4 +793,7 @@ public class ErrorParserExtensionManager {
|
||||||
return errorParser;
|
return errorParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isInContext(Pair<IErrorParserNamed, Integer> pair, int context) {
|
||||||
|
return (pair.second & context) != 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Google, Inc and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Alex Ruiz (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pair of values.
|
||||||
|
*/
|
||||||
|
public class Pair<F, S> {
|
||||||
|
public final F first;
|
||||||
|
public final S second;
|
||||||
|
|
||||||
|
public Pair(F first, S second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("<"); //$NON-NLS-1$
|
||||||
|
builder.append(first);
|
||||||
|
builder.append(">, <"); //$NON-NLS-1$
|
||||||
|
builder.append(second);
|
||||||
|
builder.append(">"); //$NON-NLS-1$
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -456,7 +456,7 @@
|
||||||
%Cproject.desc
|
%Cproject.desc
|
||||||
</description>
|
</description>
|
||||||
</wizard>
|
</wizard>
|
||||||
<wizard
|
<!-- (defered) wizard
|
||||||
canFinishEarly="false"
|
canFinishEarly="false"
|
||||||
category="org.eclipse.cdt.ui.newCWizards"
|
category="org.eclipse.cdt.ui.newCWizards"
|
||||||
class="org.eclipse.cdt.ui.wizards.NewCDTProjectWizard"
|
class="org.eclipse.cdt.ui.wizards.NewCDTProjectWizard"
|
||||||
|
@ -466,7 +466,7 @@
|
||||||
id="org.eclipse.cdt.ui.wizards.newProject"
|
id="org.eclipse.cdt.ui.wizards.newProject"
|
||||||
name="%newProjectWizard.name"
|
name="%newProjectWizard.name"
|
||||||
project="true">
|
project="true">
|
||||||
</wizard>
|
</wizard-->
|
||||||
</extension>
|
</extension>
|
||||||
|
|
||||||
<!-- Define the document setup participant for the C/C++ and Assembly Editors -->
|
<!-- Define the document setup participant for the C/C++ and Assembly Editors -->
|
||||||
|
|
|
@ -69,6 +69,7 @@ import org.eclipse.ui.texteditor.MarkerUtilities;
|
||||||
import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
|
import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
|
||||||
import org.eclipse.ui.texteditor.spelling.SpellingAnnotation;
|
import org.eclipse.ui.texteditor.spelling.SpellingAnnotation;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.model.CoreModel;
|
import org.eclipse.cdt.core.model.CoreModel;
|
||||||
import org.eclipse.cdt.core.model.ICModelMarker;
|
import org.eclipse.cdt.core.model.ICModelMarker;
|
||||||
import org.eclipse.cdt.core.model.ICProject;
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
@ -120,55 +121,38 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
fArguments= isProblem() ? problem.getArguments() : null;
|
fArguments= isProblem() ? problem.getArguments() : null;
|
||||||
setType(problem instanceof CoreSpellingProblem ?
|
setType(problem instanceof CoreSpellingProblem ?
|
||||||
SpellingAnnotation.TYPE : INDEXER_ANNOTATION_TYPE);
|
SpellingAnnotation.TYPE : INDEXER_ANNOTATION_TYPE);
|
||||||
if (problem instanceof IPersistableProblem)
|
if (problem instanceof IPersistableProblem) {
|
||||||
fMarkerType= ((IPersistableProblem) problem).getMarkerType();
|
fMarkerType= ((IPersistableProblem) problem).getMarkerType();
|
||||||
else
|
} else {
|
||||||
fMarkerType= null;
|
fMarkerType= null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see ICAnnotation#getArguments()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getArguments() {
|
public String[] getArguments() {
|
||||||
return fArguments;
|
return fArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see ICAnnotation#getId()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return fId;
|
return fId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see ICAnnotation#isProblem()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isProblem() {
|
public boolean isProblem() {
|
||||||
return fIsProblem;
|
return fIsProblem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see ICAnnotation#hasOverlay()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasOverlay() {
|
public boolean hasOverlay() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see ICAnnotation#getOverlay()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public ICAnnotation getOverlay() {
|
public ICAnnotation getOverlay() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see ICAnnotation#addOverlaid(ICAnnotation)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void addOverlaid(ICAnnotation annotation) {
|
public void addOverlaid(ICAnnotation annotation) {
|
||||||
if (fOverlaids == null)
|
if (fOverlaids == null)
|
||||||
|
@ -176,9 +160,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
fOverlaids.add(annotation);
|
fOverlaids.add(annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see ICAnnotation#removeOverlaid(ICAnnotation)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void removeOverlaid(ICAnnotation annotation) {
|
public void removeOverlaid(ICAnnotation annotation) {
|
||||||
if (fOverlaids != null) {
|
if (fOverlaids != null) {
|
||||||
|
@ -188,9 +169,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see ICAnnotation#getOverlaidIterator()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<ICAnnotation> getOverlaidIterator() {
|
public Iterator<ICAnnotation> getOverlaidIterator() {
|
||||||
if (fOverlaids != null)
|
if (fOverlaids != null)
|
||||||
|
@ -198,17 +176,11 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.cdt.internal.ui.editor.ICAnnotation#getTranslationUnit()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public ITranslationUnit getTranslationUnit() {
|
public ITranslationUnit getTranslationUnit() {
|
||||||
return fTranslationUnit;
|
return fTranslationUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipsecjdt.internal.ui.editor.ICAnnotation#getMarkerType()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getMarkerType() {
|
public String getMarkerType() {
|
||||||
return fMarkerType;
|
return fMarkerType;
|
||||||
|
@ -235,7 +207,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object get(Position position) {
|
public Object get(Position position) {
|
||||||
|
|
||||||
Entry entry;
|
Entry entry;
|
||||||
|
|
||||||
// behind anchor
|
// behind anchor
|
||||||
|
@ -300,32 +271,22 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
* A marker updater which removes problems markers with length 0.
|
* A marker updater which removes problems markers with length 0.
|
||||||
*/
|
*/
|
||||||
public static class ProblemMarkerUpdater implements IMarkerUpdater {
|
public static class ProblemMarkerUpdater implements IMarkerUpdater {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor (executable extension).
|
* Default constructor (executable extension).
|
||||||
*/
|
*/
|
||||||
public ProblemMarkerUpdater() {
|
public ProblemMarkerUpdater() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.ui.texteditor.IMarkerUpdater#getAttribute()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getAttribute() {
|
public String[] getAttribute() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.ui.texteditor.IMarkerUpdater#getMarkerType()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getMarkerType() {
|
public String getMarkerType() {
|
||||||
return ICModelMarker.C_MODEL_PROBLEM_MARKER;
|
return ICModelMarker.C_MODEL_PROBLEM_MARKER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.ui.texteditor.IMarkerUpdater#updateMarker(org.eclipse.core.resources.IMarker, org.eclipse.jface.text.IDocument, org.eclipse.jface.text.Position)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateMarker(IMarker marker, IDocument document, Position position) {
|
public boolean updateMarker(IMarker marker, IDocument document, Position position) {
|
||||||
if (position == null) {
|
if (position == null) {
|
||||||
|
@ -340,13 +301,14 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation model dealing with c marker annotations and temporary problems.
|
* Annotation model dealing with c marker annotations and temporary problems.
|
||||||
* Also acts as a problem requestor for its translation unit. Initially inactive. Must be explicitly
|
* Also acts as a problem requestor for its translation unit. Initially inactive.
|
||||||
* activated.
|
* Must be explicitly activated.
|
||||||
*/
|
*/
|
||||||
protected static class TranslationUnitAnnotationModel extends ResourceMarkerAnnotationModel implements IProblemRequestor, IProblemRequestorExtension {
|
protected static class TranslationUnitAnnotationModel extends ResourceMarkerAnnotationModel
|
||||||
|
implements IProblemRequestor, IProblemRequestorExtension {
|
||||||
|
|
||||||
private static class ProblemRequestorState {
|
private static class ProblemRequestorState {
|
||||||
boolean fInsideReportingSequence= false;
|
boolean fInsideReportingSequence;
|
||||||
List<IProblem> fReportedProblems;
|
List<IProblem> fReportedProblems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,13 +318,12 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
private ITranslationUnit fTranslationUnit;
|
private ITranslationUnit fTranslationUnit;
|
||||||
private List<ProblemAnnotation> fGeneratedAnnotations;
|
private List<ProblemAnnotation> fGeneratedAnnotations;
|
||||||
private IProgressMonitor fProgressMonitor;
|
private IProgressMonitor fProgressMonitor;
|
||||||
private boolean fIsActive= false;
|
private boolean fIsActive;
|
||||||
|
|
||||||
private ReverseMap fReverseMap= new ReverseMap();
|
private ReverseMap fReverseMap= new ReverseMap();
|
||||||
private List<CMarkerAnnotation> fPreviouslyOverlaid= null;
|
private List<CMarkerAnnotation> fPreviouslyOverlaid;
|
||||||
private List<CMarkerAnnotation> fCurrentlyOverlaid= new ArrayList<CMarkerAnnotation>();
|
private List<CMarkerAnnotation> fCurrentlyOverlaid= new ArrayList<CMarkerAnnotation>();
|
||||||
|
|
||||||
|
|
||||||
public TranslationUnitAnnotationModel(IResource resource) {
|
public TranslationUnitAnnotationModel(IResource resource) {
|
||||||
super(resource);
|
super(resource);
|
||||||
}
|
}
|
||||||
|
@ -380,10 +341,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
return super.createMarkerAnnotation(marker);
|
return super.createMarkerAnnotation(marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel#createPositionFromMarker(org.eclipse.core.resources.IMarker)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected Position createPositionFromMarker(IMarker marker) {
|
protected Position createPositionFromMarker(IMarker marker) {
|
||||||
int start= MarkerUtilities.getCharStart(marker);
|
int start= MarkerUtilities.getCharStart(marker);
|
||||||
|
@ -420,9 +377,7 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* @see org.eclipse.jface.text.source.AnnotationModel#createAnnotationModelEvent()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected AnnotationModelEvent createAnnotationModelEvent() {
|
protected AnnotationModelEvent createAnnotationModelEvent() {
|
||||||
return new TranslationUnitAnnotationModelEvent(this, getResource());
|
return new TranslationUnitAnnotationModelEvent(this, getResource());
|
||||||
|
@ -439,9 +394,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
return new Position(start, length);
|
return new Position(start, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see IProblemRequestor#beginReporting()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void beginReporting() {
|
public void beginReporting() {
|
||||||
ProblemRequestorState state= fProblemRequestorState.get();
|
ProblemRequestorState state= fProblemRequestorState.get();
|
||||||
|
@ -449,9 +401,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
internalBeginReporting(false);
|
internalBeginReporting(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.cdt.internal.ui.text.java.IProblemRequestorExtension#beginReportingSequence()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void beginReportingSequence() {
|
public void beginReportingSequence() {
|
||||||
ProblemRequestorState state= fProblemRequestorState.get();
|
ProblemRequestorState state= fProblemRequestorState.get();
|
||||||
|
@ -477,21 +426,26 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see IProblemRequestor#acceptProblem(IProblem)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptProblem(IProblem problem) {
|
public void acceptProblem(IProblem problem) {
|
||||||
if (isActive()) {
|
if (isActive()) {
|
||||||
ProblemRequestorState state= fProblemRequestorState.get();
|
ProblemRequestorState state= fProblemRequestorState.get();
|
||||||
if (state != null)
|
if (state != null && isReliable(problem)) {
|
||||||
state.fReportedProblems.add(problem);
|
state.fReportedProblems.add(problem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* @see IProblemRequestor#endReporting()
|
* A problem is not considered reliable if it belongs to an unreliable AST.
|
||||||
*/
|
*/
|
||||||
|
private static boolean isReliable(IProblem problem) {
|
||||||
|
if (problem instanceof IASTNode) {
|
||||||
|
return !((IASTNode) problem).getTranslationUnit().isBasedOnIncompleteIndex();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endReporting() {
|
public void endReporting() {
|
||||||
ProblemRequestorState state= fProblemRequestorState.get();
|
ProblemRequestorState state= fProblemRequestorState.get();
|
||||||
|
@ -499,9 +453,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
internalEndReporting(state);
|
internalEndReporting(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.cdt.internal.ui.text.java.IProblemRequestorExtension#endReportingSequence()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void endReportingSequence() {
|
public void endReportingSequence() {
|
||||||
ProblemRequestorState state= fProblemRequestorState.get();
|
ProblemRequestorState state= fProblemRequestorState.get();
|
||||||
|
@ -542,19 +493,15 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
fGeneratedAnnotations.clear();
|
fGeneratedAnnotations.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reportedProblems != null && reportedProblems.size() > 0) {
|
if (reportedProblems != null) {
|
||||||
Iterator<IProblem> e= reportedProblems.iterator();
|
for (IProblem problem : reportedProblems) {
|
||||||
while (e.hasNext()) {
|
|
||||||
|
|
||||||
if (fProgressMonitor != null && fProgressMonitor.isCanceled()) {
|
if (fProgressMonitor != null && fProgressMonitor.isCanceled()) {
|
||||||
isCanceled= true;
|
isCanceled= true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
IProblem problem= e.next();
|
|
||||||
Position position= createPositionFromProblem(problem);
|
Position position= createPositionFromProblem(problem);
|
||||||
if (position != null) {
|
if (position != null) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ProblemAnnotation annotation= new ProblemAnnotation(problem, fTranslationUnit);
|
ProblemAnnotation annotation= new ProblemAnnotation(problem, fTranslationUnit);
|
||||||
overlayMarkers(position, annotation);
|
overlayMarkers(position, annotation);
|
||||||
|
@ -563,7 +510,7 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
|
|
||||||
temporaryProblemsChanged= true;
|
temporaryProblemsChanged= true;
|
||||||
} catch (BadLocationException x) {
|
} catch (BadLocationException x) {
|
||||||
// ignore invalid position
|
// Ignore invalid position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -601,7 +548,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
fPreviouslyOverlaid.remove(annotation);
|
fPreviouslyOverlaid.remove(annotation);
|
||||||
fCurrentlyOverlaid.add(annotation);
|
fCurrentlyOverlaid.add(annotation);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,8 +555,9 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
Object value= getAnnotations(position);
|
Object value= getAnnotations(position);
|
||||||
if (value instanceof List<?>) {
|
if (value instanceof List<?>) {
|
||||||
List<?> list= (List<?>) value;
|
List<?> list= (List<?>) value;
|
||||||
for (Object element : list)
|
for (Object element : list) {
|
||||||
setOverlay(element, problemAnnotation);
|
setOverlay(element, problemAnnotation);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setOverlay(value, problemAnnotation);
|
setOverlay(value, problemAnnotation);
|
||||||
}
|
}
|
||||||
|
@ -632,25 +579,16 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
fGeneratedAnnotations= null;
|
fGeneratedAnnotations= null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see IProblemRequestor#isActive()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive() {
|
public boolean isActive() {
|
||||||
return fIsActive;
|
return fIsActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see IProblemRequestorExtension#setProgressMonitor(IProgressMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setProgressMonitor(IProgressMonitor monitor) {
|
public void setProgressMonitor(IProgressMonitor monitor) {
|
||||||
fProgressMonitor= monitor;
|
fProgressMonitor= monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see IProblemRequestorExtension#setIsActive(boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setIsActive(boolean isActive) {
|
public void setIsActive(boolean isActive) {
|
||||||
if (fIsActive != isActive) {
|
if (fIsActive != isActive) {
|
||||||
|
@ -668,9 +606,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see AnnotationModel#addAnnotation(Annotation, Position, boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
protected void addAnnotation(Annotation annotation, Position position, boolean fireModelChanged) throws BadLocationException {
|
protected void addAnnotation(Annotation annotation, Position position, boolean fireModelChanged) throws BadLocationException {
|
||||||
|
@ -692,9 +627,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see AnnotationModel#removeAllAnnotations(boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected void removeAllAnnotations(boolean fireModelChanged) {
|
protected void removeAllAnnotations(boolean fireModelChanged) {
|
||||||
super.removeAllAnnotations(fireModelChanged);
|
super.removeAllAnnotations(fireModelChanged);
|
||||||
|
@ -703,9 +635,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see AnnotationModel#removeAnnotation(Annotation, boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected void removeAnnotation(Annotation annotation, boolean fireModelChanged) {
|
protected void removeAnnotation(Annotation annotation, boolean fireModelChanged) {
|
||||||
Position position= getPosition(annotation);
|
Position position= getPosition(annotation);
|
||||||
|
@ -727,16 +656,12 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class GlobalAnnotationModelListener implements IAnnotationModelListener, IAnnotationModelListenerExtension {
|
protected static class GlobalAnnotationModelListener implements IAnnotationModelListener, IAnnotationModelListenerExtension {
|
||||||
|
|
||||||
private ListenerList fListenerList;
|
private ListenerList fListenerList;
|
||||||
|
|
||||||
public GlobalAnnotationModelListener() {
|
public GlobalAnnotationModelListener() {
|
||||||
fListenerList= new ListenerList(ListenerList.IDENTITY);
|
fListenerList= new ListenerList(ListenerList.IDENTITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see IAnnotationModelListener#modelChanged(IAnnotationModel)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modelChanged(IAnnotationModel model) {
|
public void modelChanged(IAnnotationModel model) {
|
||||||
Object[] listeners= fListenerList.getListeners();
|
Object[] listeners= fListenerList.getListeners();
|
||||||
|
@ -745,9 +670,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see IAnnotationModelListenerExtension#modelChanged(AnnotationModelEvent)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modelChanged(AnnotationModelEvent event) {
|
public void modelChanged(AnnotationModelEvent event) {
|
||||||
Object[] listeners= fListenerList.getListeners();
|
Object[] listeners= fListenerList.getListeners();
|
||||||
|
@ -775,9 +697,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
/** Annotation model listener added to all created CU annotation models */
|
/** Annotation model listener added to all created CU annotation models */
|
||||||
private GlobalAnnotationModelListener fGlobalAnnotationModelListener;
|
private GlobalAnnotationModelListener fGlobalAnnotationModelListener;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public CDocumentProvider() {
|
public CDocumentProvider() {
|
||||||
super();
|
super();
|
||||||
IDocumentProvider parentProvider= new ExternalSearchDocumentProvider();
|
IDocumentProvider parentProvider= new ExternalSearchDocumentProvider();
|
||||||
|
@ -794,9 +713,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
CUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(fPropertyListener);
|
CUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(fPropertyListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.ui.editors.text.TextFileDocumentProvider#connect(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void connect(Object element) throws CoreException {
|
public void connect(Object element) throws CoreException {
|
||||||
super.connect(element);
|
super.connect(element);
|
||||||
|
@ -811,8 +727,7 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
/**
|
/**
|
||||||
* Creates a translation unit from the given file.
|
* Creates a translation unit from the given file.
|
||||||
*
|
*
|
||||||
* @param file
|
* @param file the file from which to create the translation unit
|
||||||
* the file from which to create the translation unit
|
|
||||||
*/
|
*/
|
||||||
protected ITranslationUnit createTranslationUnit(IFile file) {
|
protected ITranslationUnit createTranslationUnit(IFile file) {
|
||||||
Object element = CoreModel.getDefault().create(file);
|
Object element = CoreModel.getDefault().create(file);
|
||||||
|
@ -820,7 +735,7 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
return (ITranslationUnit) element;
|
return (ITranslationUnit) element;
|
||||||
}
|
}
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
// not in a source folder?
|
// Not in a source folder?
|
||||||
ICProject cproject= CoreModel.getDefault().create(file.getProject());
|
ICProject cproject= CoreModel.getDefault().create(file.getProject());
|
||||||
if (cproject != null) {
|
if (cproject != null) {
|
||||||
String contentTypeId= CoreModel.getRegistedContentTypeId(file.getProject(), file.getName());
|
String contentTypeId= CoreModel.getRegistedContentTypeId(file.getProject(), file.getName());
|
||||||
|
@ -832,25 +747,16 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createEmptyFileInfo()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected FileInfo createEmptyFileInfo() {
|
protected FileInfo createEmptyFileInfo() {
|
||||||
return new TranslationUnitInfo();
|
return new TranslationUnitInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createAnnotationModel(org.eclipse.core.resources.IFile)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected IAnnotationModel createAnnotationModel(IFile file) {
|
protected IAnnotationModel createAnnotationModel(IFile file) {
|
||||||
return new TranslationUnitAnnotationModel(file);
|
return new TranslationUnitAnnotationModel(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createFileInfo(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected FileInfo createFileInfo(Object element) throws CoreException {
|
protected FileInfo createFileInfo(Object element) throws CoreException {
|
||||||
ITranslationUnit original = null;
|
ITranslationUnit original = null;
|
||||||
|
@ -915,7 +821,7 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to synthesize an ITranslationUnit out of thin air.
|
* Tries to synthesize an ITranslationUnit out of thin air.
|
||||||
* @param location the file system location of the file in question
|
* @param location the file system location of the file in question
|
||||||
* @return a translation unit or <code>null</code>
|
* @return a translation unit or <code>null</code>
|
||||||
*/
|
*/
|
||||||
|
@ -931,7 +837,7 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to synthesize an ITranslationUnit out of thin air.
|
* Tries to synthesize an ITranslationUnit out of thin air.
|
||||||
* @param uri the URU of the file in question
|
* @param uri the URU of the file in question
|
||||||
* @return a translation unit or <code>null</code>
|
* @return a translation unit or <code>null</code>
|
||||||
*/
|
*/
|
||||||
|
@ -946,10 +852,6 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.ui.editors.text.TextFileDocumentProvider#disposeFileInfo(java.lang.Object,
|
|
||||||
* org.eclipse.ui.editors.text.TextFileDocumentProvider.FileInfo)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected void disposeFileInfo(Object element, FileInfo info) {
|
protected void disposeFileInfo(Object element, FileInfo info) {
|
||||||
if (info instanceof TranslationUnitInfo) {
|
if (info instanceof TranslationUnitInfo) {
|
||||||
|
@ -1020,25 +922,17 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.ui.editors.text.TextFileDocumentProvider#createSaveOperation(java.lang.Object, org.eclipse.jface.text.IDocument, boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected DocumentProviderOperation createSaveOperation(final Object element, final IDocument document,
|
protected DocumentProviderOperation createSaveOperation(final Object element, final IDocument document,
|
||||||
final boolean overwrite) throws CoreException {
|
final boolean overwrite) throws CoreException {
|
||||||
final FileInfo info= getFileInfo(element);
|
final FileInfo info= getFileInfo(element);
|
||||||
if (info instanceof TranslationUnitInfo) {
|
if (info instanceof TranslationUnitInfo) {
|
||||||
return new DocumentProviderOperation() {
|
return new DocumentProviderOperation() {
|
||||||
/*
|
|
||||||
* @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected void execute(IProgressMonitor monitor) throws CoreException {
|
protected void execute(IProgressMonitor monitor) throws CoreException {
|
||||||
commitWorkingCopy(monitor, element, (TranslationUnitInfo) info, overwrite);
|
commitWorkingCopy(monitor, element, (TranslationUnitInfo) info, overwrite);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#getSchedulingRule()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public ISchedulingRule getSchedulingRule() {
|
public ISchedulingRule getSchedulingRule() {
|
||||||
if (info.fElement instanceof IFileEditorInput) {
|
if (info.fElement instanceof IFileEditorInput) {
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
package org.eclipse.cdt.internal.ui.editor;
|
package org.eclipse.cdt.internal.ui.editor;
|
||||||
|
|
||||||
import org.eclipse.jface.resource.ColorRegistry;
|
import org.eclipse.jface.resource.ColorRegistry;
|
||||||
|
@ -26,7 +25,6 @@ import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public abstract class SemanticHighlighting {
|
public abstract class SemanticHighlighting {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the preference key, will be augmented by a prefix and a suffix for each preference
|
* @return the preference key, will be augmented by a prefix and a suffix for each preference
|
||||||
*/
|
*/
|
||||||
|
@ -126,5 +124,4 @@ public abstract class SemanticHighlighting {
|
||||||
return rgb;
|
return rgb;
|
||||||
return defaultRGB;
|
return defaultRGB;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
BIN
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/wizban/advtosettings_wiz.png
Executable file
BIN
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/wizban/advtosettings_wiz.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 8.3 KiB |
|
@ -475,4 +475,13 @@
|
||||||
</enablement>
|
</enablement>
|
||||||
</toggleTargetFactory>
|
</toggleTargetFactory>
|
||||||
</extension>
|
</extension>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.debug.core.statusHandlers">
|
||||||
|
<statusHandler
|
||||||
|
class="org.eclipse.cdt.dsf.gdb.internal.ui.GdbStatusHandler"
|
||||||
|
code="20001"
|
||||||
|
id="org.eclipse.cdt.dsf.gdb.ui.statusHandler"
|
||||||
|
plugin="org.eclipse.cdt.dsf.gdb">
|
||||||
|
</statusHandler>
|
||||||
|
</extension>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Mentor Graphics 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:
|
||||||
|
* Mentor Graphics - Initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.dsf.gdb.internal.ui;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.debug.core.IStatusHandler;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
|
||||||
|
public class GdbStatusHandler implements IStatusHandler {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.debug.core.IStatusHandler#handleStatus(org.eclipse.core.runtime.IStatus, java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Object handleStatus( final IStatus status, Object source ) throws CoreException {
|
||||||
|
Runnable runnable = null;
|
||||||
|
if ( status.getSeverity() == IStatus.ERROR ) {
|
||||||
|
runnable = new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Shell parent = GdbUIPlugin.getActiveWorkbenchShell();
|
||||||
|
if ( parent != null )
|
||||||
|
MessageDialog.openError( parent, Messages.GdbStatusHandler_Error, status.getMessage() );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if ( status.getSeverity() == IStatus.WARNING ) {
|
||||||
|
runnable = new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Shell parent = GdbUIPlugin.getActiveWorkbenchShell();
|
||||||
|
if ( parent != null )
|
||||||
|
MessageDialog.openWarning( parent, Messages.GdbStatusHandler_Warning, status.getMessage() );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if ( status.getSeverity() == IStatus.INFO ) {
|
||||||
|
runnable = new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Shell parent = GdbUIPlugin.getActiveWorkbenchShell();
|
||||||
|
if ( parent != null )
|
||||||
|
MessageDialog.openInformation( parent, Messages.GdbStatusHandler_Information, status.getMessage() );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if ( runnable != null )
|
||||||
|
Display.getDefault().asyncExec( runnable );
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,9 @@ import org.eclipse.debug.core.DebugPlugin;
|
||||||
import org.eclipse.debug.core.ILaunch;
|
import org.eclipse.debug.core.ILaunch;
|
||||||
import org.eclipse.jface.dialogs.ErrorDialog;
|
import org.eclipse.jface.dialogs.ErrorDialog;
|
||||||
import org.eclipse.jface.preference.IPreferenceStore;
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
|
import org.eclipse.jface.resource.ImageDescriptor;
|
||||||
|
import org.eclipse.jface.resource.ImageRegistry;
|
||||||
|
import org.eclipse.swt.graphics.Image;
|
||||||
import org.eclipse.swt.widgets.Shell;
|
import org.eclipse.swt.widgets.Shell;
|
||||||
import org.eclipse.ui.IWorkbenchPage;
|
import org.eclipse.ui.IWorkbenchPage;
|
||||||
import org.eclipse.ui.IWorkbenchWindow;
|
import org.eclipse.ui.IWorkbenchWindow;
|
||||||
|
@ -227,4 +230,32 @@ public class GdbUIPlugin extends AbstractUIPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.ui.plugin.AbstractUIPlugin#initializeImageRegistry(org.eclipse.jface.resource.ImageRegistry)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void initializeImageRegistry( ImageRegistry reg ) {
|
||||||
|
super.initializeImageRegistry( reg );
|
||||||
|
declareImages( reg );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an image descriptor for the image file at the given
|
||||||
|
* plug-in relative path
|
||||||
|
*
|
||||||
|
* @param path the path
|
||||||
|
* @return the image descriptor
|
||||||
|
*/
|
||||||
|
public static ImageDescriptor getImageDescriptor(String path) {
|
||||||
|
return imageDescriptorFromPlugin(PLUGIN_ID, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Image getImage( String key ) {
|
||||||
|
return getDefault().getImageRegistry().get( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void declareImages( ImageRegistry reg ) {
|
||||||
|
reg.put( IGdbUIConstants.IMG_WIZBAN_ADVANCED_TIMEOUT_SETTINGS,
|
||||||
|
getImageDescriptor( "icons/full/wizban/advtosettings_wiz.png" ) ); //$NON-NLS-1$
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Mentor Graphics 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:
|
||||||
|
* Mentor Graphics - Initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.dsf.gdb.internal.ui;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noimplement This interface is not intended to be implemented by clients.
|
||||||
|
*
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public interface IGdbUIConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plug-in identifier (value <code>"org.eclipse.cdt.dsf.gdb.ui"</code>).
|
||||||
|
*/
|
||||||
|
public static final String PLUGIN_ID = GdbUIPlugin.PLUGIN_ID;
|
||||||
|
|
||||||
|
/** image identifier. */
|
||||||
|
public static final String IMG_WIZBAN_ADVANCED_TIMEOUT_SETTINGS = PLUGIN_ID + ".imageAdvancedTimeoutSettings"; //$NON-NLS-1$
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Mentor Graphics 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:
|
||||||
|
* Mentor Graphics - Initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.dsf.gdb.internal.ui;
|
||||||
|
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
|
||||||
|
public class Messages extends NLS {
|
||||||
|
public static String GdbStatusHandler_Error;
|
||||||
|
|
||||||
|
public static String GdbStatusHandler_Information;
|
||||||
|
|
||||||
|
public static String GdbStatusHandler_Warning;
|
||||||
|
static {
|
||||||
|
// initialize resource bundle
|
||||||
|
NLS.initializeMessages( Messages.class.getName(), Messages.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Messages() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
#######################################################################################
|
||||||
|
# Copyright (c) 2012 Mentor Graphics 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:
|
||||||
|
# Mentor Graphics - Initial API and implementation
|
||||||
|
#######################################################################################
|
||||||
|
|
||||||
|
GdbStatusHandler_Error=Error
|
||||||
|
GdbStatusHandler_Information=Information
|
||||||
|
GdbStatusHandler_Warning=Warning
|
|
@ -13,25 +13,62 @@
|
||||||
package org.eclipse.cdt.dsf.gdb.internal.ui.preferences;
|
package org.eclipse.cdt.dsf.gdb.internal.ui.preferences;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.debug.internal.ui.preferences.IntegerWithBooleanFieldEditor;
|
||||||
import org.eclipse.cdt.dsf.debug.internal.ui.preferences.StringWithBooleanFieldEditor;
|
import org.eclipse.cdt.dsf.debug.internal.ui.preferences.StringWithBooleanFieldEditor;
|
||||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.ui.launching.LaunchUIMessages;
|
import org.eclipse.cdt.dsf.gdb.internal.ui.IGdbUIConstants;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.service.command.CustomTimeoutsMap;
|
||||||
|
import org.eclipse.jface.dialogs.IDialogConstants;
|
||||||
|
import org.eclipse.jface.dialogs.TitleAreaDialog;
|
||||||
|
import org.eclipse.jface.fieldassist.ControlDecoration;
|
||||||
|
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
|
||||||
import org.eclipse.jface.preference.BooleanFieldEditor;
|
import org.eclipse.jface.preference.BooleanFieldEditor;
|
||||||
import org.eclipse.jface.preference.FieldEditorPreferencePage;
|
import org.eclipse.jface.preference.FieldEditorPreferencePage;
|
||||||
import org.eclipse.jface.preference.IPreferenceStore;
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
import org.eclipse.jface.preference.IntegerFieldEditor;
|
import org.eclipse.jface.preference.IntegerFieldEditor;
|
||||||
import org.eclipse.jface.preference.StringFieldEditor;
|
import org.eclipse.jface.preference.StringFieldEditor;
|
||||||
|
import org.eclipse.jface.resource.JFaceResources;
|
||||||
|
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||||
|
import org.eclipse.jface.viewers.CellEditor;
|
||||||
|
import org.eclipse.jface.viewers.ColumnLabelProvider;
|
||||||
|
import org.eclipse.jface.viewers.ColumnViewer;
|
||||||
|
import org.eclipse.jface.viewers.DoubleClickEvent;
|
||||||
|
import org.eclipse.jface.viewers.EditingSupport;
|
||||||
|
import org.eclipse.jface.viewers.ICellEditorListener;
|
||||||
|
import org.eclipse.jface.viewers.ICellEditorValidator;
|
||||||
|
import org.eclipse.jface.viewers.IDoubleClickListener;
|
||||||
|
import org.eclipse.jface.viewers.ISelectionChangedListener;
|
||||||
|
import org.eclipse.jface.viewers.IStructuredContentProvider;
|
||||||
|
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||||
|
import org.eclipse.jface.viewers.SelectionChangedEvent;
|
||||||
|
import org.eclipse.jface.viewers.StructuredSelection;
|
||||||
|
import org.eclipse.jface.viewers.TableViewer;
|
||||||
|
import org.eclipse.jface.viewers.TableViewerColumn;
|
||||||
|
import org.eclipse.jface.viewers.TextCellEditor;
|
||||||
|
import org.eclipse.jface.viewers.Viewer;
|
||||||
|
import org.eclipse.jface.window.Window;
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.events.ControlAdapter;
|
||||||
|
import org.eclipse.swt.events.ControlEvent;
|
||||||
import org.eclipse.swt.events.SelectionAdapter;
|
import org.eclipse.swt.events.SelectionAdapter;
|
||||||
import org.eclipse.swt.events.SelectionEvent;
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.graphics.Rectangle;
|
||||||
import org.eclipse.swt.layout.GridData;
|
import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.layout.GridLayout;
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
import org.eclipse.swt.widgets.Button;
|
import org.eclipse.swt.widgets.Button;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Control;
|
||||||
import org.eclipse.swt.widgets.FileDialog;
|
import org.eclipse.swt.widgets.FileDialog;
|
||||||
import org.eclipse.swt.widgets.Group;
|
import org.eclipse.swt.widgets.Group;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.eclipse.swt.widgets.Table;
|
||||||
|
import org.eclipse.swt.widgets.TableColumn;
|
||||||
import org.eclipse.ui.IWorkbench;
|
import org.eclipse.ui.IWorkbench;
|
||||||
import org.eclipse.ui.IWorkbenchPreferencePage;
|
import org.eclipse.ui.IWorkbenchPreferencePage;
|
||||||
import org.eclipse.ui.PlatformUI;
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
@ -41,6 +78,7 @@ import org.eclipse.ui.PlatformUI;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("restriction")
|
@SuppressWarnings("restriction")
|
||||||
public class GdbDebugPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
|
public class GdbDebugPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A vehicle in order to be able to register a selection listener with
|
* A vehicle in order to be able to register a selection listener with
|
||||||
* a {@link BooleanFieldEditor}.
|
* a {@link BooleanFieldEditor}.
|
||||||
|
@ -58,20 +96,428 @@ public class GdbDebugPreferencePage extends FieldEditorPreferencePage implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AdvancedTimeoutSettingsDialog extends TitleAreaDialog {
|
||||||
|
|
||||||
|
class CommandTimeoutEntry {
|
||||||
|
|
||||||
|
String fCommand;
|
||||||
|
Integer fTimeout;
|
||||||
|
|
||||||
|
CommandTimeoutEntry( String command, Integer timeout ) {
|
||||||
|
fCommand = command;
|
||||||
|
fTimeout = timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CellEditorListener implements ICellEditorListener {
|
||||||
|
|
||||||
|
CellEditor fEditor;
|
||||||
|
|
||||||
|
public CellEditorListener( CellEditor editor ) {
|
||||||
|
super();
|
||||||
|
fEditor = editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void editorValueChanged( boolean oldValidState, boolean newValidState ) {
|
||||||
|
if ( newValidState ) {
|
||||||
|
setErrorMessage( null );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setErrorMessage( fEditor.getErrorMessage() );
|
||||||
|
}
|
||||||
|
updateDialogButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelEditor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyEditorValue() {
|
||||||
|
validate();
|
||||||
|
updateDialogButtons();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract class AbstractEditingSupport extends EditingSupport {
|
||||||
|
|
||||||
|
public AbstractEditingSupport( ColumnViewer viewer ) {
|
||||||
|
super( viewer );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setValue( Object element, Object value ) {
|
||||||
|
if ( element instanceof CommandTimeoutEntry && value instanceof String ) {
|
||||||
|
if ( processValue( (CommandTimeoutEntry)element, (String)value ) ) {
|
||||||
|
fViewer.refresh( element );
|
||||||
|
validate();
|
||||||
|
updateDialogButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object getValue( Object element ) {
|
||||||
|
if ( element instanceof CommandTimeoutEntry ) {
|
||||||
|
return doGetValue( (CommandTimeoutEntry)element );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CellEditor getCellEditor( Object element ) {
|
||||||
|
final CellEditor editor = new TextCellEditor( (Composite)getViewer().getControl() );
|
||||||
|
editor.setValidator( getValidator() );
|
||||||
|
editor.addListener( new CellEditorListener( editor ) );
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canEdit( Object element ) {
|
||||||
|
return ( element instanceof CommandTimeoutEntry );
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract boolean processValue( CommandTimeoutEntry entry, String value );
|
||||||
|
|
||||||
|
abstract Object doGetValue( CommandTimeoutEntry entry );
|
||||||
|
|
||||||
|
abstract ICellEditorValidator getValidator();
|
||||||
|
};
|
||||||
|
|
||||||
|
private TableViewer fViewer;
|
||||||
|
private Button fAddButton;
|
||||||
|
private Button fDeleteButton;
|
||||||
|
|
||||||
|
private List<CommandTimeoutEntry> fEntries;
|
||||||
|
|
||||||
|
final private ICellEditorValidator fCommandValidator = new ICellEditorValidator() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String isValid( Object value ) {
|
||||||
|
if ( value instanceof String && ((String)value).trim().length() == 0 ) {
|
||||||
|
return MessagesForPreferences.GdbDebugPreferencePage_Command_field_can_not_be_empty;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
final private ICellEditorValidator fTimeoutValidator = new ICellEditorValidator() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String isValid( Object value ) {
|
||||||
|
if ( value instanceof String ) {
|
||||||
|
try {
|
||||||
|
int intValue = Integer.decode( (String)value ).intValue();
|
||||||
|
if ( intValue < 0 )
|
||||||
|
return MessagesForPreferences.GdbDebugPreferencePage_Timeout_value_can_not_be_negative;
|
||||||
|
}
|
||||||
|
catch( NumberFormatException e ) {
|
||||||
|
return MessagesForPreferences.GdbDebugPreferencePage_Invalid_timeout_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AdvancedTimeoutSettingsDialog( Shell parentShell, Set<Map.Entry<String, Integer>> entries ) {
|
||||||
|
super( parentShell );
|
||||||
|
setShellStyle(getShellStyle() | SWT.RESIZE);
|
||||||
|
fEntries = new LinkedList<CommandTimeoutEntry>();
|
||||||
|
for ( Map.Entry<String, Integer> entry : entries ) {
|
||||||
|
fEntries.add( new CommandTimeoutEntry( entry.getKey(), entry.getValue() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Control createDialogArea( Composite parent ) {
|
||||||
|
getShell().setText( MessagesForPreferences.GdbDebugPreferencePage_Advanced_Timeout_Settings );
|
||||||
|
setTitle( MessagesForPreferences.GdbDebugPreferencePage_Advanced_timeout_dialog_title );
|
||||||
|
setTitleImage( GdbUIPlugin.getImage( IGdbUIConstants.IMG_WIZBAN_ADVANCED_TIMEOUT_SETTINGS ) );
|
||||||
|
setMessage( MessagesForPreferences.GdbDebugPreferencePage_Advanced_timeout_dialog_message );
|
||||||
|
|
||||||
|
Composite control = (Composite)super.createDialogArea( parent );
|
||||||
|
Composite comp = new Composite( control, SWT.NONE );
|
||||||
|
GridData gd = new GridData( SWT.FILL, SWT.FILL, true, true );
|
||||||
|
GridLayout layout = new GridLayout( 2, false );
|
||||||
|
layout.marginLeft = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth();
|
||||||
|
comp.setLayout( layout );
|
||||||
|
comp.setLayoutData( gd );
|
||||||
|
|
||||||
|
fViewer = new TableViewer( comp, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER );
|
||||||
|
final Table table = fViewer.getTable();
|
||||||
|
gd = new GridData( SWT.FILL, SWT.FILL, true, true );
|
||||||
|
gd.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth();
|
||||||
|
table.setLayoutData( gd );
|
||||||
|
|
||||||
|
ControlDecoration decoration = new ControlDecoration( table, SWT.TOP | SWT.LEFT, control );
|
||||||
|
decoration.setImage(
|
||||||
|
FieldDecorationRegistry.getDefault().getFieldDecoration(
|
||||||
|
FieldDecorationRegistry.DEC_INFORMATION ).getImage() );
|
||||||
|
decoration.setDescriptionText(
|
||||||
|
MessagesForPreferences.GdbDebugPreferencePage_Advanced_timeout_settings_dialog_tooltip );
|
||||||
|
fViewer.addDoubleClickListener( new IDoubleClickListener() {
|
||||||
|
@Override
|
||||||
|
public void doubleClick( DoubleClickEvent event ) {
|
||||||
|
okPressed();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
fViewer.addSelectionChangedListener( new ISelectionChangedListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectionChanged( SelectionChangedEvent event ) {
|
||||||
|
updateDialogButtons();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
Composite btnComp = new Composite( comp, SWT.NONE );
|
||||||
|
btnComp.setLayout( new GridLayout() );
|
||||||
|
btnComp.setLayoutData( new GridData( SWT.RIGHT, SWT.TOP, false, false ) );
|
||||||
|
|
||||||
|
fAddButton = new Button( btnComp, SWT.PUSH );
|
||||||
|
fAddButton.setText( MessagesForPreferences.GdbDebugPreferencePage_Add_button );
|
||||||
|
fAddButton.setFont( JFaceResources.getDialogFont() );
|
||||||
|
setButtonLayoutData( fAddButton );
|
||||||
|
fAddButton.addSelectionListener( new SelectionAdapter() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void widgetSelected( SelectionEvent e ) {
|
||||||
|
addNewEntry();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
fDeleteButton = new Button( btnComp, SWT.PUSH );
|
||||||
|
fDeleteButton.setText( MessagesForPreferences.GdbDebugPreferencePage_Delete_button );
|
||||||
|
fDeleteButton.setFont( JFaceResources.getDialogFont() );
|
||||||
|
setButtonLayoutData( fDeleteButton );
|
||||||
|
fDeleteButton.addSelectionListener( new SelectionAdapter() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void widgetSelected( SelectionEvent e ) {
|
||||||
|
deleteEntries();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
table.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
|
||||||
|
table.setHeaderVisible( true );
|
||||||
|
table.setLinesVisible( true );
|
||||||
|
|
||||||
|
TableViewerColumn commandColumn = new TableViewerColumn( fViewer, SWT.LEFT );
|
||||||
|
commandColumn.getColumn().setText( MessagesForPreferences.GdbDebugPreferencePage_Command_column_name );
|
||||||
|
commandColumn.setLabelProvider( createCommandLabelProvider() );
|
||||||
|
commandColumn.setEditingSupport( createCommandEditingSupport( fViewer ) );
|
||||||
|
|
||||||
|
TableViewerColumn timeoutColumn = new TableViewerColumn( fViewer, SWT.LEFT );
|
||||||
|
timeoutColumn.getColumn().setText( MessagesForPreferences.GdbDebugPreferencePage_Timeout_column_name );
|
||||||
|
timeoutColumn.setLabelProvider( createTimeoutLabelProvider() );
|
||||||
|
timeoutColumn.setEditingSupport( createTimeoutEditingSupport( fViewer ) );
|
||||||
|
|
||||||
|
fViewer.setContentProvider( createCustomTimeoutsContentProvider() );
|
||||||
|
|
||||||
|
table.addControlListener( new ControlAdapter() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void controlResized( ControlEvent e ) {
|
||||||
|
Rectangle area = table.getClientArea();
|
||||||
|
if ( area.width > 0 ) {
|
||||||
|
TableColumn[] cols = table.getColumns();
|
||||||
|
cols[0].setWidth( area.width * 50 / 100 );
|
||||||
|
cols[1].setWidth( area.width * 50 / 100 );
|
||||||
|
table.removeControlListener( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
fViewer.setInput( fEntries );
|
||||||
|
|
||||||
|
updateDialogButtons();
|
||||||
|
|
||||||
|
return control;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateDialogButtons() {
|
||||||
|
if ( fViewer != null && fDeleteButton != null ) {
|
||||||
|
fDeleteButton.setEnabled( !fViewer.getSelection().isEmpty() );
|
||||||
|
}
|
||||||
|
Button okButton = getButton( IDialogConstants.OK_ID );
|
||||||
|
if ( okButton != null )
|
||||||
|
okButton.setEnabled( getErrorMessage() == null );
|
||||||
|
}
|
||||||
|
|
||||||
|
void addNewEntry() {
|
||||||
|
CommandTimeoutEntry newEntry = new CommandTimeoutEntry( "", Integer.valueOf( 0 ) ); //$NON-NLS-1$
|
||||||
|
fEntries.add( newEntry );
|
||||||
|
fViewer.refresh();
|
||||||
|
fViewer.setSelection( new StructuredSelection( newEntry ) );
|
||||||
|
validateEntry( newEntry );
|
||||||
|
updateDialogButtons();
|
||||||
|
fViewer.editElement( newEntry, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteEntries() {
|
||||||
|
IStructuredSelection sel = (IStructuredSelection)fViewer.getSelection();
|
||||||
|
if ( !sel.isEmpty() )
|
||||||
|
fEntries.removeAll( sel.toList() );
|
||||||
|
fViewer.refresh();
|
||||||
|
validate();
|
||||||
|
updateDialogButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomTimeoutsMap getResult() {
|
||||||
|
CustomTimeoutsMap map = new CustomTimeoutsMap();
|
||||||
|
for ( CommandTimeoutEntry entry : fEntries ) {
|
||||||
|
map.put( entry.fCommand, entry.fTimeout );
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void validate() {
|
||||||
|
for ( CommandTimeoutEntry entry : fEntries ) {
|
||||||
|
validateEntry( entry );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void validateEntry( CommandTimeoutEntry entry ) {
|
||||||
|
String errorMessage = fCommandValidator.isValid( entry.fCommand );
|
||||||
|
setErrorMessage( ( errorMessage != null ) ?
|
||||||
|
errorMessage : fTimeoutValidator.isValid( entry.fTimeout.toString() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
IStructuredContentProvider createCustomTimeoutsContentProvider() {
|
||||||
|
return new IStructuredContentProvider() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void inputChanged( Viewer viewer, Object oldInput, Object newInput ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] getElements( Object inputElement ) {
|
||||||
|
if ( inputElement instanceof List<?> ) {
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
List<CommandTimeoutEntry> list = (List<CommandTimeoutEntry>)inputElement;
|
||||||
|
return list.toArray( new Object[list.size()] );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLabelProvider createCommandLabelProvider() {
|
||||||
|
return new ColumnLabelProvider() {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.jface.viewers.ColumnLabelProvider#getText(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getText( Object element ) {
|
||||||
|
if ( element instanceof CommandTimeoutEntry ) {
|
||||||
|
return ((CommandTimeoutEntry)element).fCommand;
|
||||||
|
}
|
||||||
|
return super.getText( element );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLabelProvider createTimeoutLabelProvider() {
|
||||||
|
return new ColumnLabelProvider() {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.jface.viewers.ColumnLabelProvider#getText(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getText( Object element ) {
|
||||||
|
if ( element instanceof CommandTimeoutEntry ) {
|
||||||
|
return ((CommandTimeoutEntry)element).fTimeout.toString();
|
||||||
|
}
|
||||||
|
return super.getText( element );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
EditingSupport createCommandEditingSupport( ColumnViewer viewer ) {
|
||||||
|
return new AbstractEditingSupport( viewer ) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean processValue( CommandTimeoutEntry entry, String value ) {
|
||||||
|
entry.fCommand = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Object doGetValue( CommandTimeoutEntry entry ) {
|
||||||
|
return entry.fCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
ICellEditorValidator getValidator() {
|
||||||
|
return fCommandValidator;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
EditingSupport createTimeoutEditingSupport( ColumnViewer viewer ) {
|
||||||
|
return new AbstractEditingSupport( viewer ) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean processValue( CommandTimeoutEntry entry, String value ) {
|
||||||
|
try {
|
||||||
|
entry.fTimeout = Integer.decode( value );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch( NumberFormatException e ) {
|
||||||
|
// Shouldn't happen, validator takes care of this case.
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Object doGetValue( CommandTimeoutEntry entry ) {
|
||||||
|
return entry.fTimeout.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
ICellEditorValidator getValidator() {
|
||||||
|
return fTimeoutValidator;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntegerWithBooleanFieldEditor fCommandTimeoutField;
|
||||||
|
private Button fTimeoutAdvancedButton;
|
||||||
|
|
||||||
|
private CustomTimeoutsMap fCustomTimeouts;
|
||||||
|
|
||||||
public GdbDebugPreferencePage() {
|
public GdbDebugPreferencePage() {
|
||||||
super(FLAT);
|
super(FLAT);
|
||||||
IPreferenceStore store= GdbUIPlugin.getDefault().getPreferenceStore();
|
IPreferenceStore store= GdbUIPlugin.getDefault().getPreferenceStore();
|
||||||
setPreferenceStore(store);
|
setPreferenceStore(store);
|
||||||
setDescription(MessagesForPreferences.GdbDebugPreferencePage_description);
|
setDescription(MessagesForPreferences.GdbDebugPreferencePage_description);
|
||||||
|
fCustomTimeouts = new CustomTimeoutsMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IWorkbench workbench) {
|
public void init(IWorkbench workbench) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
initializeCustomTimeouts();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createControl(Composite parent) {
|
public void createControl(Composite parent) {
|
||||||
super.createControl(parent);
|
super.createControl(parent);
|
||||||
|
updateTimeoutButtons();
|
||||||
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
|
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
|
||||||
GdbUIPlugin.PLUGIN_ID + ".dsfgdb_preference_page"); //$NON-NLS-1$
|
GdbUIPlugin.PLUGIN_ID + ".dsfgdb_preference_page"); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
@ -91,44 +537,46 @@ public class GdbDebugPreferencePage extends FieldEditorPreferencePage implements
|
||||||
|
|
||||||
final StringFieldEditor stringFieldEditorCommand = new StringFieldEditor(
|
final StringFieldEditor stringFieldEditorCommand = new StringFieldEditor(
|
||||||
IGdbDebugPreferenceConstants.PREF_DEFAULT_GDB_COMMAND,
|
IGdbDebugPreferenceConstants.PREF_DEFAULT_GDB_COMMAND,
|
||||||
LaunchUIMessages.getString("GDBDebuggerPage.gdb_debugger"), //$NON-NLS-1$
|
"GDB debugger:", //$NON-NLS-1$
|
||||||
group1);
|
group1);
|
||||||
|
|
||||||
stringFieldEditorCommand.fillIntoGrid(group1, 2);
|
stringFieldEditorCommand.fillIntoGrid(group1, 2);
|
||||||
addField(stringFieldEditorCommand);
|
addField(stringFieldEditorCommand);
|
||||||
Button browsebutton = new Button(group1, SWT.PUSH);
|
Button browsebutton = new Button(group1, SWT.PUSH);
|
||||||
browsebutton.setText(LaunchUIMessages.getString("GDBDebuggerPage.gdb_browse")); //$NON-NLS-1$
|
browsebutton.setText("&Browse..."); //$NON-NLS-1$
|
||||||
browsebutton.addSelectionListener(new SelectionAdapter() {
|
browsebutton.addSelectionListener(new SelectionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void widgetSelected(SelectionEvent e) {
|
public void widgetSelected(SelectionEvent e) {
|
||||||
handleBrowseButtonSelected(LaunchUIMessages.getString("GDBDebuggerPage.gdb_browse_dlg_title"), //$NON-NLS-1$
|
handleBrowseButtonSelected("GDB Debugger", //$NON-NLS-1$
|
||||||
stringFieldEditorCommand);
|
stringFieldEditorCommand);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setButtonLayoutData( browsebutton );
|
||||||
|
|
||||||
final StringFieldEditor stringFieldEditorGdbInit = new StringFieldEditor(
|
final StringFieldEditor stringFieldEditorGdbInit = new StringFieldEditor(
|
||||||
IGdbDebugPreferenceConstants.PREF_DEFAULT_GDB_INIT,
|
IGdbDebugPreferenceConstants.PREF_DEFAULT_GDB_INIT,
|
||||||
LaunchUIMessages.getString("GDBDebuggerPage.gdb_command_file"), //$NON-NLS-1$
|
"GDB command file:", //$NON-NLS-1$
|
||||||
group1);
|
group1);
|
||||||
|
|
||||||
stringFieldEditorGdbInit.fillIntoGrid(group1, 2);
|
stringFieldEditorGdbInit.fillIntoGrid(group1, 2);
|
||||||
addField(stringFieldEditorGdbInit);
|
addField(stringFieldEditorGdbInit);
|
||||||
browsebutton = new Button(group1, SWT.PUSH);
|
browsebutton = new Button(group1, SWT.PUSH);
|
||||||
browsebutton.setText(LaunchUIMessages.getString("GDBDebuggerPage.gdb_browse")); //$NON-NLS-1$
|
browsebutton.setText("&Browse..."); //$NON-NLS-1$
|
||||||
browsebutton.addSelectionListener(new SelectionAdapter() {
|
browsebutton.addSelectionListener(new SelectionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void widgetSelected(SelectionEvent e) {
|
public void widgetSelected(SelectionEvent e) {
|
||||||
handleBrowseButtonSelected(LaunchUIMessages.getString("GDBDebuggerPage.gdb_cmdfile_dlg_title"), //$NON-NLS-1$
|
handleBrowseButtonSelected("GDB Command File", //$NON-NLS-1$
|
||||||
stringFieldEditorGdbInit);
|
stringFieldEditorGdbInit);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setButtonLayoutData( browsebutton );
|
||||||
|
|
||||||
final StringWithBooleanFieldEditor enableStopAtMain = new StringWithBooleanFieldEditor(
|
final StringWithBooleanFieldEditor enableStopAtMain = new StringWithBooleanFieldEditor(
|
||||||
IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN,
|
IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN,
|
||||||
IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN_SYMBOL,
|
IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN_SYMBOL,
|
||||||
LaunchUIMessages.getString("CDebuggerTab.Stop_at_main_on_startup"), //$NON-NLS-1$
|
"Stop on startup at:", //$NON-NLS-1$
|
||||||
group1);
|
group1);
|
||||||
enableStopAtMain.fillIntoGrid(group1, 2);
|
enableStopAtMain.fillIntoGrid(group1, 3);
|
||||||
addField(enableStopAtMain);
|
addField(enableStopAtMain);
|
||||||
|
|
||||||
// final StringFieldEditor stopAtMainSymbol = new StringFieldEditor(
|
// final StringFieldEditor stopAtMainSymbol = new StringFieldEditor(
|
||||||
|
@ -145,9 +593,29 @@ public class GdbDebugPreferencePage extends FieldEditorPreferencePage implements
|
||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
fCommandTimeoutField = new IntegerWithBooleanFieldEditor(
|
||||||
|
IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT,
|
||||||
|
IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE,
|
||||||
|
MessagesForPreferences.GdbDebugPreferencePage_Command_timeout,
|
||||||
|
group1);
|
||||||
|
fCommandTimeoutField.setValidRange(0, Integer.MAX_VALUE);
|
||||||
|
fCommandTimeoutField.fillIntoGrid(group1, 2);
|
||||||
|
addField(fCommandTimeoutField);
|
||||||
|
|
||||||
|
fTimeoutAdvancedButton = new Button(group1, SWT.PUSH);
|
||||||
|
fTimeoutAdvancedButton.setText(MessagesForPreferences.GdbDebugPreferencePage_Advanced_button);
|
||||||
|
fTimeoutAdvancedButton.addSelectionListener(new SelectionAdapter() {
|
||||||
|
@Override
|
||||||
|
public void widgetSelected(SelectionEvent e) {
|
||||||
|
handleAdvancedButtonSelected(
|
||||||
|
"GDB Debugger"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setButtonLayoutData( fTimeoutAdvancedButton );
|
||||||
|
|
||||||
final ListenableBooleanFieldEditor enableNonStop= new ListenableBooleanFieldEditor(
|
final ListenableBooleanFieldEditor enableNonStop= new ListenableBooleanFieldEditor(
|
||||||
IGdbDebugPreferenceConstants.PREF_DEFAULT_NON_STOP,
|
IGdbDebugPreferenceConstants.PREF_DEFAULT_NON_STOP,
|
||||||
LaunchUIMessages.getString("GDBDebuggerPage.nonstop_mode"), //$NON-NLS-1$
|
"Non-stop mode (Note: Requires non-stop GDB)", //$NON-NLS-1$
|
||||||
SWT.NONE, group1);
|
SWT.NONE, group1);
|
||||||
enableNonStop.fillIntoGrid(group1, 3);
|
enableNonStop.fillIntoGrid(group1, 3);
|
||||||
addField(enableNonStop);
|
addField(enableNonStop);
|
||||||
|
@ -286,8 +754,56 @@ public class GdbDebugPreferencePage extends FieldEditorPreferencePage implements
|
||||||
stringFieldEditor.setStringValue(res);
|
stringFieldEditor.setStringValue(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleAdvancedButtonSelected(String dialogTitle) {
|
||||||
|
AdvancedTimeoutSettingsDialog dialog =
|
||||||
|
new AdvancedTimeoutSettingsDialog( getShell(), fCustomTimeouts.entrySet() );
|
||||||
|
if ( dialog.open() == Window.OK ) {
|
||||||
|
fCustomTimeouts = dialog.getResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void adjustGridLayout() {
|
protected void adjustGridLayout() {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void propertyChange( PropertyChangeEvent event ) {
|
||||||
|
if ( event.getSource().equals( fCommandTimeoutField ) && event.getNewValue() instanceof Boolean ) {
|
||||||
|
fTimeoutAdvancedButton.setEnabled( ((Boolean)event.getNewValue()).booleanValue() );
|
||||||
|
}
|
||||||
|
super.propertyChange( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void performDefaults() {
|
||||||
|
IPreferenceStore store = getPreferenceStore();
|
||||||
|
if ( store != null ) {
|
||||||
|
String memento = store.getDefaultString( IGdbDebugPreferenceConstants.PREF_COMMAND_CUSTOM_TIMEOUTS );
|
||||||
|
fCustomTimeouts.initializeFromMemento( memento );
|
||||||
|
}
|
||||||
|
super.performDefaults();
|
||||||
|
updateTimeoutButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.jface.preference.FieldEditorPreferencePage#performOk()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean performOk() {
|
||||||
|
getPreferenceStore().setValue( IGdbDebugPreferenceConstants.PREF_COMMAND_CUSTOM_TIMEOUTS, fCustomTimeouts.getMemento() );
|
||||||
|
return super.performOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTimeoutButtons() {
|
||||||
|
fTimeoutAdvancedButton.setEnabled( fCommandTimeoutField.getBooleanValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeCustomTimeouts() {
|
||||||
|
IPreferenceStore store = getPreferenceStore();
|
||||||
|
if ( store != null ) {
|
||||||
|
String memento = store.getString( IGdbDebugPreferenceConstants.PREF_COMMAND_CUSTOM_TIMEOUTS );
|
||||||
|
fCustomTimeouts.initializeFromMemento( memento );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,12 @@ import org.eclipse.osgi.util.NLS;
|
||||||
* Preference strings.
|
* Preference strings.
|
||||||
*/
|
*/
|
||||||
class MessagesForPreferences extends NLS {
|
class MessagesForPreferences extends NLS {
|
||||||
|
public static String GdbDebugPreferencePage_Add_button;
|
||||||
|
public static String GdbDebugPreferencePage_Advanced_button;
|
||||||
|
public static String GdbDebugPreferencePage_Advanced_timeout_dialog_message;
|
||||||
|
public static String GdbDebugPreferencePage_Advanced_timeout_dialog_title;
|
||||||
|
public static String GdbDebugPreferencePage_Advanced_timeout_settings_dialog_tooltip;
|
||||||
|
public static String GdbDebugPreferencePage_Advanced_Timeout_Settings;
|
||||||
public static String GdbDebugPreferencePage_description;
|
public static String GdbDebugPreferencePage_description;
|
||||||
public static String GdbDebugPreferencePage_traces_label;
|
public static String GdbDebugPreferencePage_traces_label;
|
||||||
public static String GdbDebugPreferencePage_enableTraces_label;
|
public static String GdbDebugPreferencePage_enableTraces_label;
|
||||||
|
@ -24,6 +30,9 @@ class MessagesForPreferences extends NLS {
|
||||||
public static String GdbDebugPreferencePage_maxGdbTraces_label;
|
public static String GdbDebugPreferencePage_maxGdbTraces_label;
|
||||||
public static String GdbDebugPreferencePage_termination_label;
|
public static String GdbDebugPreferencePage_termination_label;
|
||||||
public static String GdbDebugPreferencePage_autoTerminateGdb_label;
|
public static String GdbDebugPreferencePage_autoTerminateGdb_label;
|
||||||
|
public static String GdbDebugPreferencePage_Command_column_name;
|
||||||
|
public static String GdbDebugPreferencePage_Command_field_can_not_be_empty;
|
||||||
|
public static String GdbDebugPreferencePage_Command_timeout;
|
||||||
public static String GdbDebugPreferencePage_hover_label;
|
public static String GdbDebugPreferencePage_hover_label;
|
||||||
public static String GdbDebugPreferencePage_useInspectorHover_label;
|
public static String GdbDebugPreferencePage_useInspectorHover_label;
|
||||||
/** @since 2.2 */
|
/** @since 2.2 */
|
||||||
|
@ -36,6 +45,10 @@ class MessagesForPreferences extends NLS {
|
||||||
public static String GdbDebugPreferencePage_initialChildCountLimitForCollections_label;
|
public static String GdbDebugPreferencePage_initialChildCountLimitForCollections_label;
|
||||||
/** @since 2.2 */
|
/** @since 2.2 */
|
||||||
public static String GdbDebugPreferencePage_defaults_label;
|
public static String GdbDebugPreferencePage_defaults_label;
|
||||||
|
public static String GdbDebugPreferencePage_Delete_button;
|
||||||
|
public static String GdbDebugPreferencePage_Invalid_timeout_value;
|
||||||
|
public static String GdbDebugPreferencePage_Timeout_column_name;
|
||||||
|
public static String GdbDebugPreferencePage_Timeout_value_can_not_be_negative;
|
||||||
static {
|
static {
|
||||||
// initialize resource bundle
|
// initialize resource bundle
|
||||||
NLS.initializeMessages(MessagesForPreferences.class.getName(), MessagesForPreferences.class);
|
NLS.initializeMessages(MessagesForPreferences.class.getName(), MessagesForPreferences.class);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
# Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
|
# Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
GdbDebugPreferencePage_Add_button=Add
|
||||||
GdbDebugPreferencePage_description=General settings for GDB Debugging
|
GdbDebugPreferencePage_description=General settings for GDB Debugging
|
||||||
|
|
||||||
GdbDebugPreferencePage_traces_label=Traces
|
GdbDebugPreferencePage_traces_label=Traces
|
||||||
|
@ -17,6 +18,9 @@ GdbDebugPreferencePage_enableTraces_label=Enable GDB traces
|
||||||
GdbDebugPreferencePage_maxGdbTraces_label=Limit GDB traces output (number of characters):
|
GdbDebugPreferencePage_maxGdbTraces_label=Limit GDB traces output (number of characters):
|
||||||
GdbDebugPreferencePage_termination_label=Termination
|
GdbDebugPreferencePage_termination_label=Termination
|
||||||
GdbDebugPreferencePage_autoTerminateGdb_label=Terminate GDB when last process exits
|
GdbDebugPreferencePage_autoTerminateGdb_label=Terminate GDB when last process exits
|
||||||
|
GdbDebugPreferencePage_Command_column_name=GDB/MI Command
|
||||||
|
GdbDebugPreferencePage_Command_field_can_not_be_empty='Command' field can not be empty
|
||||||
|
GdbDebugPreferencePage_Command_timeout=Command timeout (ms):
|
||||||
|
|
||||||
GdbDebugPreferencePage_hover_label=Debug Text Hover
|
GdbDebugPreferencePage_hover_label=Debug Text Hover
|
||||||
GdbDebugPreferencePage_useInspectorHover_label=Use enhanced debug hover
|
GdbDebugPreferencePage_useInspectorHover_label=Use enhanced debug hover
|
||||||
|
@ -27,3 +31,13 @@ GdbDebugPreferencePage_enablePrettyPrinting_label2=(requires python-enabled GDB)
|
||||||
GdbDebugPreferencePage_initialChildCountLimitForCollections_label=For collections, initially limit child count to
|
GdbDebugPreferencePage_initialChildCountLimitForCollections_label=For collections, initially limit child count to
|
||||||
|
|
||||||
GdbDebugPreferencePage_defaults_label=Debug Configurations Defaults
|
GdbDebugPreferencePage_defaults_label=Debug Configurations Defaults
|
||||||
|
GdbDebugPreferencePage_Delete_button=Delete
|
||||||
|
GdbDebugPreferencePage_Invalid_timeout_value=Invalid timeout value
|
||||||
|
GdbDebugPreferencePage_Timeout_column_name=Timeout(ms)
|
||||||
|
GdbDebugPreferencePage_Timeout_value_can_not_be_negative=Timeout value can not be negative
|
||||||
|
|
||||||
|
GdbDebugPreferencePage_Advanced_button=&Advanced...
|
||||||
|
GdbDebugPreferencePage_Advanced_timeout_dialog_message=Specify commands and corresponding timeout values.
|
||||||
|
GdbDebugPreferencePage_Advanced_timeout_dialog_title=Add/delete/modify custom timeouts for GDB/MI commands
|
||||||
|
GdbDebugPreferencePage_Advanced_timeout_settings_dialog_tooltip=Specify commands and corresponding timeout values, use zero for "no timeout".\nMI commands must start with hyphen ('-'). For example, '-target-select'.\nThe default value will be used for all commands that are not mentioned here.
|
||||||
|
GdbDebugPreferencePage_Advanced_Timeout_Settings=Advanced Timeout Settings
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
org.eclipse.cdt.dsf.gdb/debug = false
|
org.eclipse.cdt.dsf.gdb/debug = false
|
||||||
|
org.eclipse.cdt.dsf.gdb/debug/timeouts = false
|
||||||
|
|
|
@ -16,7 +16,6 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @noimplement This interface is not intended to be implemented by clients.
|
* @noimplement This interface is not intended to be implemented by clients.
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
|
@ -25,6 +24,12 @@ public interface IGdbDebugConstants {
|
||||||
|
|
||||||
public static final String PREFIX = GdbPlugin.PLUGIN_ID + "."; //$NON-NLS-1$
|
public static final String PREFIX = GdbPlugin.PLUGIN_ID + "."; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status code for which a UI handler is registered.
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public static final int STATUS_HANDLER_CODE = 20001;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attribute key to be added to the IProcess associated with an IMIContainerDMContext.
|
* Attribute key to be added to the IProcess associated with an IMIContainerDMContext.
|
||||||
* The value should be the groupId as returned by {@link IMIContainerDMContext#getGroupId()}
|
* The value should be the groupId as returned by {@link IMIContainerDMContext#getGroupId()}
|
||||||
|
@ -54,6 +59,5 @@ public interface IGdbDebugConstants {
|
||||||
*/
|
*/
|
||||||
public static final String GDB_PROCESS_CREATION_VALUE = PREFIX + "gdbProcess"; //$NON-NLS-1$
|
public static final String GDB_PROCESS_CREATION_VALUE = PREFIX + "gdbProcess"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,11 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
public interface IGdbDebugPreferenceConstants {
|
public interface IGdbDebugPreferenceConstants {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Help prefixes.
|
||||||
|
*/
|
||||||
|
public static final String PREFIX = GdbPlugin.PLUGIN_ID + "."; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
* Boolean preference whether to enable GDB traces. Default is <code>true</code>.
|
* Boolean preference whether to enable GDB traces. Default is <code>true</code>.
|
||||||
*/
|
*/
|
||||||
public static final String PREF_TRACES_ENABLE = "tracesEnable"; //$NON-NLS-1$
|
public static final String PREF_TRACES_ENABLE = "tracesEnable"; //$NON-NLS-1$
|
||||||
|
@ -87,8 +92,27 @@ public interface IGdbDebugPreferenceConstants {
|
||||||
public static final String PREF_DEFAULT_NON_STOP = "defaultNonStop"; //$NON-NLS-1$
|
public static final String PREF_DEFAULT_NON_STOP = "defaultNonStop"; //$NON-NLS-1$
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Help prefixes.
|
* The value is an boolean specifying whether the timeout is used for GDB commands.
|
||||||
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
public static final String PREFIX = GdbPlugin.PLUGIN_ID + "."; //$NON-NLS-1$
|
public static final String PREF_COMMAND_TIMEOUT = PREFIX + "commandTimeout"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value is an integer specifying the timeout value (milliseconds) for GDB commands.
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public static final String PREF_COMMAND_TIMEOUT_VALUE = PREFIX + "commandTimeoutValue"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value is a string specifying the list of GDB/MI commands with custom timeout values.
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public static final String PREF_COMMAND_CUSTOM_TIMEOUTS = PREFIX + "commandCustomTimeouts"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default default value for <code>PREF_COMMAND_TIMEOUT</code>;
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public static final int COMMAND_TIMEOUT_VALUE_DEFAULT = 10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,5 +38,7 @@ public class GdbPreferenceInitializer extends AbstractPreferenceInitializer {
|
||||||
node.putBoolean(IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_DEFAULT);
|
node.putBoolean(IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_DEFAULT);
|
||||||
node.put(IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN_SYMBOL, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT);
|
node.put(IGdbDebugPreferenceConstants.PREF_DEFAULT_STOP_AT_MAIN_SYMBOL, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT);
|
||||||
node.putBoolean(IGdbDebugPreferenceConstants.PREF_DEFAULT_NON_STOP, IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
|
node.putBoolean(IGdbDebugPreferenceConstants.PREF_DEFAULT_NON_STOP, IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
|
||||||
|
node.putBoolean(IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, false);
|
||||||
|
node.putInt(IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Mentor Graphics 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:
|
||||||
|
* Mentor Graphics - Initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.dsf.gdb.internal;
|
||||||
|
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
|
||||||
|
public class Messages extends NLS {
|
||||||
|
|
||||||
|
public static String CustomTimeoutsMap_Error_initializing_custom_timeouts;
|
||||||
|
|
||||||
|
public static String CustomTimeoutsMap_Invalid_custom_timeout_data;
|
||||||
|
|
||||||
|
public static String CustomTimeoutsMap_Invalid_custom_timeout_value;
|
||||||
|
|
||||||
|
public static String GDBControl_Session_is_terminated;
|
||||||
|
static {
|
||||||
|
// initialize resource bundle
|
||||||
|
NLS.initializeMessages( Messages.class.getName(), Messages.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Messages() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#######################################################################################
|
||||||
|
# Copyright (c) 2011 Mentor Graphics 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:
|
||||||
|
# Mentor Graphics - Initial API and implementation
|
||||||
|
#######################################################################################
|
||||||
|
|
||||||
|
CustomTimeoutsMap_Error_initializing_custom_timeouts=Error initializing custom timeouts
|
||||||
|
CustomTimeoutsMap_Invalid_custom_timeout_data=Invalid custom timeout data.
|
||||||
|
CustomTimeoutsMap_Invalid_custom_timeout_value=Invalid custom timeout value for '%s'.
|
||||||
|
GDBControl_Session_is_terminated=Session is terminated.\nReason: %s
|
|
@ -449,9 +449,9 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
return (threadState == null) ? false : !fTerminated && threadState.fSuspended;
|
return (threadState == null) ? false : !fTerminated && threadState.fSuspended;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container case. The container is considered suspended as long
|
// Process case. The process is considered suspended as long
|
||||||
// as one of its thread is suspended
|
// as one of its thread is suspended
|
||||||
if (context instanceof IContainerDMContext) {
|
if (context instanceof IMIContainerDMContext) {
|
||||||
boolean hasThread = false;
|
boolean hasThread = false;
|
||||||
for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
|
for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
|
||||||
if (DMContexts.isAncestorOf(threadContext, context)) {
|
if (DMContexts.isAncestorOf(threadContext, context)) {
|
||||||
|
@ -471,41 +471,36 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
@Override
|
@Override
|
||||||
public void canSuspend(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
public void canSuspend(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
||||||
if (fRunControlOperationsEnabled == false) {
|
if (fRunControlOperationsEnabled == false) {
|
||||||
rm.setData(false);
|
rm.done(false);
|
||||||
rm.done();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thread case
|
rm.done(doCanSuspend(context));
|
||||||
if (context instanceof IMIExecutionDMContext) {
|
|
||||||
rm.setData(doCanSuspend(context));
|
|
||||||
rm.done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Container case
|
|
||||||
if (context instanceof IContainerDMContext) {
|
|
||||||
boolean canSuspend = false;
|
|
||||||
for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
|
|
||||||
if (DMContexts.isAncestorOf(threadContext, context)) {
|
|
||||||
canSuspend |= doCanSuspend(threadContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rm.setData(canSuspend);
|
|
||||||
rm.done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default case
|
|
||||||
rm.setData(false);
|
|
||||||
rm.done();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doCanSuspend(IExecutionDMContext context) {
|
private boolean doCanSuspend(IExecutionDMContext context) {
|
||||||
|
// Thread case
|
||||||
|
if (context instanceof IMIExecutionDMContext) {
|
||||||
MIThreadRunState threadState = fThreadRunStates.get(context);
|
MIThreadRunState threadState = fThreadRunStates.get(context);
|
||||||
return (threadState == null) ? false : !fTerminated && !threadState.fSuspended;
|
return (threadState == null) ? false : !fTerminated && !threadState.fSuspended;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process case
|
||||||
|
if (context instanceof IMIContainerDMContext) {
|
||||||
|
for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
|
||||||
|
if (DMContexts.isAncestorOf(threadContext, context)) {
|
||||||
|
if (doCanSuspend(threadContext)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default case
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void suspend(IExecutionDMContext context, final RequestMonitor rm) {
|
public void suspend(IExecutionDMContext context, final RequestMonitor rm) {
|
||||||
|
|
||||||
|
@ -514,14 +509,14 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
// Thread case
|
// Thread case
|
||||||
IMIExecutionDMContext thread = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
|
IMIExecutionDMContext thread = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
|
||||||
if (thread != null) {
|
if (thread != null) {
|
||||||
doSuspendThread(thread, rm);
|
doSuspend(thread, rm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container case
|
// Process case
|
||||||
IMIContainerDMContext container = DMContexts.getAncestorOfType(context, IMIContainerDMContext.class);
|
IMIContainerDMContext container = DMContexts.getAncestorOfType(context, IMIContainerDMContext.class);
|
||||||
if (container != null) {
|
if (container != null) {
|
||||||
doSuspendContainer(container, rm);
|
doSuspend(container, rm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,8 +525,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doSuspendThread(IMIExecutionDMContext context, final RequestMonitor rm) {
|
private void doSuspend(IMIExecutionDMContext context, final RequestMonitor rm) {
|
||||||
|
|
||||||
if (!doCanSuspend(context)) {
|
if (!doCanSuspend(context)) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
|
||||||
"Given context: " + context + ", is already suspended.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
"Given context: " + context + ", is already suspended.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
@ -542,7 +536,14 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
fConnection.queueCommand(fCommandFactory.createMIExecInterrupt(context), new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
fConnection.queueCommand(fCommandFactory.createMIExecInterrupt(context), new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doSuspendContainer(IMIContainerDMContext context, final RequestMonitor rm) {
|
private void doSuspend(IMIContainerDMContext context, final RequestMonitor rm) {
|
||||||
|
if (!doCanSuspend(context)) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
|
||||||
|
"Given context: " + context + ", is already suspended.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String groupId = context.getGroupId();
|
String groupId = context.getGroupId();
|
||||||
fConnection.queueCommand(fCommandFactory.createMIExecInterrupt(context, groupId), new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
fConnection.queueCommand(fCommandFactory.createMIExecInterrupt(context, groupId), new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||||
}
|
}
|
||||||
|
@ -554,41 +555,36 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
@Override
|
@Override
|
||||||
public void canResume(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
public void canResume(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
||||||
if (fRunControlOperationsEnabled == false) {
|
if (fRunControlOperationsEnabled == false) {
|
||||||
rm.setData(false);
|
rm.done(false);
|
||||||
rm.done();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thread case
|
rm.done(doCanResume(context));
|
||||||
if (context instanceof IMIExecutionDMContext) {
|
|
||||||
rm.setData(doCanResume(context));
|
|
||||||
rm.done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Container case
|
|
||||||
if (context instanceof IContainerDMContext) {
|
|
||||||
boolean canSuspend = false;
|
|
||||||
for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
|
|
||||||
if (DMContexts.isAncestorOf(threadContext, context)) {
|
|
||||||
canSuspend |= doCanResume(threadContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rm.setData(canSuspend);
|
|
||||||
rm.done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default case
|
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Invalid context type.", null)); //$NON-NLS-1$
|
|
||||||
rm.done();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doCanResume(IExecutionDMContext context) {
|
private boolean doCanResume(IExecutionDMContext context) {
|
||||||
|
// Thread case
|
||||||
|
if (context instanceof IMIExecutionDMContext) {
|
||||||
MIThreadRunState threadState = fThreadRunStates.get(context);
|
MIThreadRunState threadState = fThreadRunStates.get(context);
|
||||||
return (threadState == null) ? false : !fTerminated && threadState.fSuspended && !threadState.fResumePending;
|
return (threadState == null) ? false : !fTerminated && threadState.fSuspended && !threadState.fResumePending;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process case
|
||||||
|
if (context instanceof IMIContainerDMContext) {
|
||||||
|
for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
|
||||||
|
if (DMContexts.isAncestorOf(threadContext, context)) {
|
||||||
|
if (doCanResume(threadContext)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default case
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resume(IExecutionDMContext context, final RequestMonitor rm) {
|
public void resume(IExecutionDMContext context, final RequestMonitor rm) {
|
||||||
|
|
||||||
|
@ -597,14 +593,14 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
// Thread case
|
// Thread case
|
||||||
IMIExecutionDMContext thread = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
|
IMIExecutionDMContext thread = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
|
||||||
if (thread != null) {
|
if (thread != null) {
|
||||||
doResumeThread(thread, rm);
|
doResume(thread, rm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container case
|
// Container case
|
||||||
IMIContainerDMContext container = DMContexts.getAncestorOfType(context, IMIContainerDMContext.class);
|
IMIContainerDMContext container = DMContexts.getAncestorOfType(context, IMIContainerDMContext.class);
|
||||||
if (container != null) {
|
if (container != null) {
|
||||||
doResumeContainer(container, rm);
|
doResume(container, rm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,8 +609,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doResumeThread(IMIExecutionDMContext context, final RequestMonitor rm) {
|
private void doResume(IMIExecutionDMContext context, final RequestMonitor rm) {
|
||||||
|
|
||||||
if (!doCanResume(context)) {
|
if (!doCanResume(context)) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
|
||||||
"Given context: " + context + ", is already running.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
"Given context: " + context + ", is already running.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
@ -640,7 +635,14 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doResumeContainer(IMIContainerDMContext context, final RequestMonitor rm) {
|
private void doResume(IMIContainerDMContext context, final RequestMonitor rm) {
|
||||||
|
if (!doCanResume(context)) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
|
||||||
|
"Given context: " + context + ", is already running.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String groupId = context.getGroupId();
|
String groupId = context.getGroupId();
|
||||||
fConnection.queueCommand(fCommandFactory.createMIExecContinue(context, groupId), new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
fConnection.queueCommand(fCommandFactory.createMIExecContinue(context, groupId), new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||||
}
|
}
|
||||||
|
@ -665,8 +667,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
@Override
|
@Override
|
||||||
public void canStep(final IExecutionDMContext context, StepType stepType, final DataRequestMonitor<Boolean> rm) {
|
public void canStep(final IExecutionDMContext context, StepType stepType, final DataRequestMonitor<Boolean> rm) {
|
||||||
if (fRunControlOperationsEnabled == false) {
|
if (fRunControlOperationsEnabled == false) {
|
||||||
rm.setData(false);
|
rm.done(false);
|
||||||
rm.done();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,8 +684,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
@Override
|
@Override
|
||||||
public void handleCompleted() {
|
public void handleCompleted() {
|
||||||
if (isSuccess() && getData() == 1) {
|
if (isSuccess() && getData() == 1) {
|
||||||
rm.setData(false);
|
rm.done(false);
|
||||||
rm.done();
|
|
||||||
} else {
|
} else {
|
||||||
canResume(context, rm);
|
canResume(context, rm);
|
||||||
}
|
}
|
||||||
|
@ -699,8 +699,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's a container, then we don't want to step it
|
// If it's a container, then we don't want to step it
|
||||||
rm.setData(false);
|
rm.done(false);
|
||||||
rm.done();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -710,24 +709,21 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
|
|
||||||
IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
|
IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
|
||||||
if (dmc == null) {
|
if (dmc == null) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR,
|
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR,
|
||||||
"Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
"Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
rm.done();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!doCanResume(context)) {
|
if (!doCanResume(dmc)) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
|
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
|
||||||
"Cannot resume context", null)); //$NON-NLS-1$
|
"Cannot resume context", null)); //$NON-NLS-1$
|
||||||
rm.done();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final MIThreadRunState threadState = fThreadRunStates.get(context);
|
final MIThreadRunState threadState = fThreadRunStates.get(context);
|
||||||
if (threadState == null) {
|
if (threadState == null) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
|
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
|
||||||
"Given context: " + context + " can't be found.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
"Given context: " + context + " can't be found.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
rm.done();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -751,9 +747,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
IFrameDMContext topFrameDmc = stackService.createFrameDMContext(dmc, 0);
|
IFrameDMContext topFrameDmc = stackService.createFrameDMContext(dmc, 0);
|
||||||
cmd = fCommandFactory.createMIExecFinish(topFrameDmc);
|
cmd = fCommandFactory.createMIExecFinish(topFrameDmc);
|
||||||
} else {
|
} else {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
|
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
|
||||||
"Cannot create context for command, stack service not available.", null)); //$NON-NLS-1$
|
"Cannot create context for command, stack service not available.", null)); //$NON-NLS-1$
|
||||||
rm.done();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -764,9 +759,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
cmd = fCommandFactory.createMIExecNextInstruction(dmc);
|
cmd = fCommandFactory.createMIExecNextInstruction(dmc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
||||||
INTERNAL_ERROR, "Given step type not supported", null)); //$NON-NLS-1$
|
INTERNAL_ERROR, "Given step type not supported", null)); //$NON-NLS-1$
|
||||||
rm.done();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,12 +148,12 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
if (getData()) {
|
if (getData()) {
|
||||||
if (thread != null) {
|
if (thread != null) {
|
||||||
doResumeThread(thread, rm);
|
doResume(thread, rm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container != null) {
|
if (container != null) {
|
||||||
doResumeContainer(container, rm);
|
doResume(container, rm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -165,7 +165,7 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doResumeThread(IMIExecutionDMContext context, final RequestMonitor rm) {
|
private void doResume(IMIExecutionDMContext context, final RequestMonitor rm) {
|
||||||
final MIThreadRunState threadState = fThreadRunStates.get(context);
|
final MIThreadRunState threadState = fThreadRunStates.get(context);
|
||||||
if (threadState == null) {
|
if (threadState == null) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
|
||||||
|
@ -184,7 +184,7 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doResumeContainer(IMIContainerDMContext context, final RequestMonitor rm) {
|
private void doResume(IMIContainerDMContext context, final RequestMonitor rm) {
|
||||||
fConnection.queueCommand(fCommandFactory.createMIExecContinue(context), new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
fConnection.queueCommand(fCommandFactory.createMIExecContinue(context), new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Mentor Graphics 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:
|
||||||
|
* Mentor Graphics - Initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.dsf.gdb.service.command;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.internal.Messages;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.MultiStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public class CustomTimeoutsMap extends HashMap<String, Integer> {
|
||||||
|
|
||||||
|
public CustomTimeoutsMap() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomTimeoutsMap( CustomTimeoutsMap map ) {
|
||||||
|
super( map );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -8281280275781904870L;
|
||||||
|
|
||||||
|
public String getMemento() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for ( Map.Entry<String, Integer> entry : entrySet() ) {
|
||||||
|
sb.append( entry.getKey() );
|
||||||
|
sb.append( ',' );
|
||||||
|
sb.append( entry.getValue().intValue() );
|
||||||
|
sb.append( ';' );
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializeFromMemento( String memento ) {
|
||||||
|
clear();
|
||||||
|
StringTokenizer st = new StringTokenizer( memento, ";" ); //$NON-NLS-1$
|
||||||
|
MultiStatus ms = new MultiStatus( GdbPlugin.PLUGIN_ID, 0, Messages.CustomTimeoutsMap_Error_initializing_custom_timeouts, null );
|
||||||
|
while( st.hasMoreTokens() ) {
|
||||||
|
String token = st.nextToken();
|
||||||
|
String[] tokenParts = token.split( "," ); //$NON-NLS-1$
|
||||||
|
if ( tokenParts.length == 2 && tokenParts[0].length() > 0 && tokenParts[1].length() > 0 ) {
|
||||||
|
try {
|
||||||
|
put( tokenParts[0], Integer.valueOf( tokenParts[1] ) );
|
||||||
|
}
|
||||||
|
catch( NumberFormatException e ) {
|
||||||
|
ms.add( new Status(
|
||||||
|
IStatus.ERROR,
|
||||||
|
GdbPlugin.PLUGIN_ID,
|
||||||
|
String.format( Messages.CustomTimeoutsMap_Invalid_custom_timeout_value, tokenParts[0] ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ms.add( new Status(
|
||||||
|
IStatus.ERROR,
|
||||||
|
GdbPlugin.PLUGIN_ID,
|
||||||
|
Messages.CustomTimeoutsMap_Invalid_custom_timeout_data ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !ms.isOK() ) {
|
||||||
|
GdbPlugin.getDefault().getLog().log( ms );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ import java.util.Properties;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
|
@ -43,10 +44,14 @@ import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandToken;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.IGdbDebugConstants;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.internal.Messages;
|
||||||
import org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence;
|
import org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
|
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.service.command.GdbCommandTimeoutManager.ICommandTimeoutListener;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend.BackendStateChangedEvent;
|
import org.eclipse.cdt.dsf.mi.service.IMIBackend.BackendStateChangedEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend2;
|
import org.eclipse.cdt.dsf.mi.service.IMIBackend2;
|
||||||
|
@ -69,8 +74,10 @@ import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.debug.core.DebugPlugin;
|
||||||
import org.eclipse.debug.core.ILaunch;
|
import org.eclipse.debug.core.ILaunch;
|
||||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.core.IStatusHandler;
|
||||||
import org.osgi.framework.BundleContext;
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,6 +89,8 @@ import org.osgi.framework.BundleContext;
|
||||||
*/
|
*/
|
||||||
public class GDBControl extends AbstractMIControl implements IGDBControl {
|
public class GDBControl extends AbstractMIControl implements IGDBControl {
|
||||||
|
|
||||||
|
private static final int STATUS_CODE_COMMAND_TIMED_OUT = 20100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event indicating that the back end process has started.
|
* Event indicating that the back end process has started.
|
||||||
*/
|
*/
|
||||||
|
@ -104,6 +113,20 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TimeoutListener implements ICommandTimeoutListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void commandTimedOut(final ICommandToken token) {
|
||||||
|
getExecutor().execute(new DsfRunnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
GDBControl.this.commandTimedOut(token);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private GDBControlDMContext fControlDmc;
|
private GDBControlDMContext fControlDmc;
|
||||||
|
|
||||||
private IGDBBackend fMIBackend;
|
private IGDBBackend fMIBackend;
|
||||||
|
@ -112,6 +135,10 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
||||||
private IEventProcessor fCLICommandProcessor;
|
private IEventProcessor fCLICommandProcessor;
|
||||||
private AbstractCLIProcess fCLIProcess;
|
private AbstractCLIProcess fCLIProcess;
|
||||||
|
|
||||||
|
private GdbCommandTimeoutManager fCommandTimeoutManager;
|
||||||
|
|
||||||
|
private ICommandTimeoutListener fTimeoutListener = new TimeoutListener();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GDBControl is only used for GDB earlier that 7.0. Although -list-features
|
* GDBControl is only used for GDB earlier that 7.0. Although -list-features
|
||||||
* is available in 6.8, it does not report anything we care about, so
|
* is available in 6.8, it does not report anything we care about, so
|
||||||
|
@ -121,6 +148,14 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
||||||
|
|
||||||
private Sequence fInitializationSequence;
|
private Sequence fInitializationSequence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicator to distinguish whether this service is initialized.
|
||||||
|
* <code>fInitializationSequence</code> can not be used for this
|
||||||
|
* purpose because there is a period of time when the service is already
|
||||||
|
* initializing but the initialization sequence has not created yet.
|
||||||
|
*/
|
||||||
|
private boolean fInitialized = false;
|
||||||
|
|
||||||
private boolean fTerminated;
|
private boolean fTerminated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -308,6 +343,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
||||||
@Override
|
@Override
|
||||||
protected void handleCompleted() {
|
protected void handleCompleted() {
|
||||||
fInitializationSequence = null;
|
fInitializationSequence = null;
|
||||||
|
fInitialized = true;
|
||||||
if (!isCanceled()) {
|
if (!isCanceled()) {
|
||||||
// Only set the status if the user has not cancelled the operation already.
|
// Only set the status if the user has not cancelled the operation already.
|
||||||
rm.setStatus(getStatus());
|
rm.setStatus(getStatus());
|
||||||
|
@ -440,6 +476,33 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
protected class CommandTimeoutStep extends InitializationShutdownStep {
|
||||||
|
CommandTimeoutStep( Direction direction ) {
|
||||||
|
super( direction );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize( final RequestMonitor requestMonitor ) {
|
||||||
|
fCommandTimeoutManager = createCommandTimeoutManager( GDBControl.this );
|
||||||
|
if (fCommandTimeoutManager != null) {
|
||||||
|
fCommandTimeoutManager.addCommandTimeoutListener(fTimeoutListener);
|
||||||
|
}
|
||||||
|
requestMonitor.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void shutdown( RequestMonitor requestMonitor ) {
|
||||||
|
if ( fCommandTimeoutManager != null ) {
|
||||||
|
fCommandTimeoutManager.removeCommandTimeoutListener(fTimeoutListener);
|
||||||
|
fCommandTimeoutManager.dispose();
|
||||||
|
}
|
||||||
|
requestMonitor.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected class RegisterStep extends InitializationShutdownStep {
|
protected class RegisterStep extends InitializationShutdownStep {
|
||||||
RegisterStep(Direction direction) { super(direction); }
|
RegisterStep(Direction direction) { super(direction); }
|
||||||
@Override
|
@Override
|
||||||
|
@ -493,6 +556,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
||||||
final Sequence.Step[] initializeSteps = new Sequence.Step[] {
|
final Sequence.Step[] initializeSteps = new Sequence.Step[] {
|
||||||
new CommandMonitoringStep(InitializationShutdownStep.Direction.INITIALIZING),
|
new CommandMonitoringStep(InitializationShutdownStep.Direction.INITIALIZING),
|
||||||
new CommandProcessorsStep(InitializationShutdownStep.Direction.INITIALIZING),
|
new CommandProcessorsStep(InitializationShutdownStep.Direction.INITIALIZING),
|
||||||
|
new CommandTimeoutStep(InitializationShutdownStep.Direction.INITIALIZING),
|
||||||
new RegisterStep(InitializationShutdownStep.Direction.INITIALIZING),
|
new RegisterStep(InitializationShutdownStep.Direction.INITIALIZING),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -507,6 +571,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
||||||
protected Sequence getShutdownSequence(RequestMonitor requestMonitor) {
|
protected Sequence getShutdownSequence(RequestMonitor requestMonitor) {
|
||||||
final Sequence.Step[] shutdownSteps = new Sequence.Step[] {
|
final Sequence.Step[] shutdownSteps = new Sequence.Step[] {
|
||||||
new RegisterStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
new RegisterStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
||||||
|
new CommandTimeoutStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
||||||
new CommandProcessorsStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
new CommandProcessorsStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
||||||
new CommandMonitoringStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
new CommandMonitoringStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
||||||
};
|
};
|
||||||
|
@ -536,4 +601,63 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
||||||
fFeatures.clear();
|
fFeatures.clear();
|
||||||
fFeatures.addAll(features);
|
fFeatures.addAll(features);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
protected GdbCommandTimeoutManager createCommandTimeoutManager(ICommandControl commandControl) {
|
||||||
|
GdbCommandTimeoutManager manager = new GdbCommandTimeoutManager(commandControl);
|
||||||
|
manager.initialize();
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
@ConfinedToDsfExecutor("this.getExecutor()")
|
||||||
|
protected void commandTimedOut(ICommandToken token) {
|
||||||
|
String commandText = token.getCommand().toString();
|
||||||
|
if (commandText.endsWith("\n")) //$NON-NLS-1$
|
||||||
|
commandText = commandText.substring(0, commandText.length() - 1);
|
||||||
|
final String errorMessage = String.format("Command '%s' is timed out", commandText); //$NON-NLS-1$
|
||||||
|
commandFailed(token, STATUS_CODE_COMMAND_TIMED_OUT, errorMessage);
|
||||||
|
|
||||||
|
// If the timeout occurs while the launch sequence is running
|
||||||
|
// the error will be reported by the launcher's error reporting mechanism.
|
||||||
|
// We need to show the error message only when the session is initialized.
|
||||||
|
if (isInitialized()) {
|
||||||
|
// The session is terminated if a command is timed out.
|
||||||
|
terminate(new RequestMonitor(getExecutor(), null) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleErrorOrWarning() {
|
||||||
|
GdbPlugin.getDefault().getLog().log(getStatus());
|
||||||
|
super.handleErrorOrWarning();
|
||||||
|
};
|
||||||
|
} );
|
||||||
|
|
||||||
|
IStatus status = new Status(
|
||||||
|
IStatus.ERROR,
|
||||||
|
GdbPlugin.PLUGIN_ID,
|
||||||
|
IGdbDebugConstants.STATUS_HANDLER_CODE,
|
||||||
|
String.format( Messages.GDBControl_Session_is_terminated, errorMessage ),
|
||||||
|
null);
|
||||||
|
IStatusHandler statusHandler = DebugPlugin.getDefault().getStatusHandler(status);
|
||||||
|
if (statusHandler != null) {
|
||||||
|
try {
|
||||||
|
statusHandler.handleStatus(status, null);
|
||||||
|
}
|
||||||
|
catch(CoreException e) {
|
||||||
|
GdbPlugin.getDefault().getLog().log(e.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
protected boolean isInitialized() {
|
||||||
|
return fInitialized;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,7 @@ public class GDBControl_7_0 extends GDBControl {
|
||||||
final Sequence.Step[] initializeSteps = new Sequence.Step[] {
|
final Sequence.Step[] initializeSteps = new Sequence.Step[] {
|
||||||
new GDBControl.CommandMonitoringStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING),
|
new GDBControl.CommandMonitoringStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING),
|
||||||
new GDBControl.CommandProcessorsStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING),
|
new GDBControl.CommandProcessorsStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING),
|
||||||
|
new CommandTimeoutStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING),
|
||||||
new ListFeaturesStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING),
|
new ListFeaturesStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING),
|
||||||
new GDBControl.RegisterStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING),
|
new GDBControl.RegisterStep(GDBControl.InitializationShutdownStep.Direction.INITIALIZING),
|
||||||
};
|
};
|
||||||
|
@ -161,6 +162,7 @@ public class GDBControl_7_0 extends GDBControl {
|
||||||
final Sequence.Step[] shutdownSteps = new Sequence.Step[] {
|
final Sequence.Step[] shutdownSteps = new Sequence.Step[] {
|
||||||
new GDBControl.RegisterStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
new GDBControl.RegisterStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
||||||
new ListFeaturesStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
new ListFeaturesStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
||||||
|
new CommandTimeoutStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
||||||
new GDBControl.CommandProcessorsStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
new GDBControl.CommandProcessorsStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
||||||
new GDBControl.CommandMonitoringStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
new GDBControl.CommandMonitoringStep(GDBControl.InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,443 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Mentor Graphics 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:
|
||||||
|
* Mentor Graphics - Initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.dsf.gdb.service.command;
|
||||||
|
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
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.ICommandListener;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandResult;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandToken;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.AbstractMIControl;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.ListenerList;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
|
||||||
|
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
|
||||||
|
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
|
||||||
|
import org.eclipse.core.runtime.preferences.InstanceScope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command timeout manager registers itself as a command listener and monitors
|
||||||
|
* the command execution time. The goal of this implementation is to gracefully
|
||||||
|
* handle disruptions in the communication between Eclipse and GDB.
|
||||||
|
*
|
||||||
|
* The algorithm used by this class is based on the assumption that the command
|
||||||
|
* execution in GDB is sequential even though DSF can send up to 3 commands at
|
||||||
|
* a time to GDB (see {@link AbstractMIControl}).
|
||||||
|
*
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public class GdbCommandTimeoutManager implements ICommandListener, IPreferenceChangeListener {
|
||||||
|
|
||||||
|
public interface ICommandTimeoutListener {
|
||||||
|
|
||||||
|
void commandTimedOut( ICommandToken token );
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static boolean DEBUG = "true".equals( Platform.getDebugOption( "org.eclipse.cdt.dsf.gdb/debug/timeouts" ) ); //$NON-NLS-1$//$NON-NLS-2$
|
||||||
|
|
||||||
|
private class QueueEntry {
|
||||||
|
private long fTimestamp;
|
||||||
|
private ICommandToken fCommandToken;
|
||||||
|
|
||||||
|
private QueueEntry( long timestamp, ICommandToken commandToken ) {
|
||||||
|
super();
|
||||||
|
fTimestamp = timestamp;
|
||||||
|
fCommandToken = commandToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#equals(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object obj ) {
|
||||||
|
if ( obj instanceof QueueEntry ) {
|
||||||
|
return fCommandToken.equals( ((QueueEntry)obj).fCommandToken );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum TimerThreadState {
|
||||||
|
INITIALIZING,
|
||||||
|
RUNNING,
|
||||||
|
HALTED,
|
||||||
|
SHUTDOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TimerThread extends Thread {
|
||||||
|
|
||||||
|
private BlockingQueue<QueueEntry> fQueue;
|
||||||
|
private int fWaitTimeout = IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT;
|
||||||
|
private TimerThreadState fState = TimerThreadState.INITIALIZING;
|
||||||
|
|
||||||
|
TimerThread( BlockingQueue<QueueEntry> queue, int timeout ) {
|
||||||
|
super();
|
||||||
|
setName( "GDB Command Timer Thread" ); //$NON-NLS-1$
|
||||||
|
fQueue = queue;
|
||||||
|
setWaitTimout( timeout );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.lang.Thread#run()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
setTimerThreadState( ( getWaitTimeout() > 0 ) ?
|
||||||
|
TimerThreadState.RUNNING : TimerThreadState.HALTED );
|
||||||
|
doRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doRun() {
|
||||||
|
while ( getTimerThreadState() != TimerThreadState.SHUTDOWN ) {
|
||||||
|
if ( getTimerThreadState() == TimerThreadState.HALTED ) {
|
||||||
|
halted();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
running();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void halted() {
|
||||||
|
fQueue.clear();
|
||||||
|
try {
|
||||||
|
synchronized( TimerThread.this ) {
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( InterruptedException e ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void running() {
|
||||||
|
try {
|
||||||
|
while( getTimerThreadState() == TimerThreadState.RUNNING ) {
|
||||||
|
// Use the minimum of all timeout values > 0 as the wait timeout.
|
||||||
|
long timeout = getWaitTimeout();
|
||||||
|
QueueEntry entry = fQueue.peek();
|
||||||
|
if ( entry != null ) {
|
||||||
|
// Calculate the time elapsed since the execution of this command started
|
||||||
|
// and compare it with the command's timeout value.
|
||||||
|
// If the elapsed time is greater or equal than the timeout value the command
|
||||||
|
// is marked as timed out. Otherwise, schedule the next check when the timeout
|
||||||
|
// expires.
|
||||||
|
long commandTimeout = getTimeoutForCommand( entry.fCommandToken.getCommand() );
|
||||||
|
|
||||||
|
if ( DEBUG ) {
|
||||||
|
String commandText = entry.fCommandToken.getCommand().toString();
|
||||||
|
if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$
|
||||||
|
commandText = commandText.substring( 0, commandText.length() - 1 );
|
||||||
|
printDebugMessage( String.format( "Processing command '%s', command timeout is %d", //$NON-NLS-1$
|
||||||
|
commandText, Long.valueOf( commandTimeout ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
long elapsedTime = currentTime - entry.fTimestamp;
|
||||||
|
if ( commandTimeout <= elapsedTime ) {
|
||||||
|
processTimedOutCommand( entry.fCommandToken );
|
||||||
|
fQueue.remove( entry );
|
||||||
|
// Reset the timestamp of the next command in the queue because
|
||||||
|
// regardless how long the command has been in the queue GDB will
|
||||||
|
// start executing it only when the execution of the previous command
|
||||||
|
// is completed.
|
||||||
|
QueueEntry nextEntry = fQueue.peek();
|
||||||
|
if ( nextEntry != null ) {
|
||||||
|
setTimeStamp( currentTime, nextEntry );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Adjust the wait timeout because the time remaining for
|
||||||
|
// the current command to expire may be less than the current wait timeout.
|
||||||
|
timeout = Math.min( timeout, commandTimeout - elapsedTime );
|
||||||
|
|
||||||
|
if ( DEBUG ) {
|
||||||
|
String commandText = entry.fCommandToken.getCommand().toString();
|
||||||
|
if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$
|
||||||
|
commandText = commandText.substring( 0, commandText.length() - 1 );
|
||||||
|
printDebugMessage( String.format( "Setting timeout %d for command '%s'", Long.valueOf( timeout ), commandText ) ); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
synchronized( TimerThread.this ) {
|
||||||
|
wait( timeout );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( InterruptedException e ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void shutdown() {
|
||||||
|
setTimerThreadState( TimerThreadState.SHUTDOWN );
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void setWaitTimout( int waitTimeout ) {
|
||||||
|
fWaitTimeout = waitTimeout;
|
||||||
|
if ( DEBUG )
|
||||||
|
printDebugMessage( String.format( "Wait timeout is set to %d", Integer.valueOf( fWaitTimeout ) ) ); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized int getWaitTimeout() {
|
||||||
|
return fWaitTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void setTimerThreadState( TimerThreadState state ) {
|
||||||
|
fState = state;
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized TimerThreadState getTimerThreadState() {
|
||||||
|
return fState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String TIMEOUT_TRACE_IDENTIFIER = "[TMO]"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private ICommandControl fCommandControl;
|
||||||
|
private boolean fTimeoutEnabled = false;
|
||||||
|
private int fTimeout = 0;
|
||||||
|
private TimerThread fTimerThread;
|
||||||
|
private BlockingQueue<QueueEntry> fCommandQueue = new LinkedBlockingQueue<QueueEntry>();
|
||||||
|
private CustomTimeoutsMap fCustomTimeouts = new CustomTimeoutsMap();
|
||||||
|
|
||||||
|
private ListenerList fListeners;
|
||||||
|
|
||||||
|
public GdbCommandTimeoutManager( ICommandControl commandControl ) {
|
||||||
|
fCommandControl = commandControl;
|
||||||
|
fListeners = new ListenerList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID );
|
||||||
|
|
||||||
|
fTimeoutEnabled = Platform.getPreferencesService().getBoolean(
|
||||||
|
GdbPlugin.PLUGIN_ID,
|
||||||
|
IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT,
|
||||||
|
false,
|
||||||
|
null );
|
||||||
|
|
||||||
|
fTimeout = Platform.getPreferencesService().getInt(
|
||||||
|
GdbPlugin.PLUGIN_ID,
|
||||||
|
IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE,
|
||||||
|
IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT,
|
||||||
|
null );
|
||||||
|
|
||||||
|
fCustomTimeouts.initializeFromMemento( Platform.getPreferencesService().getString(
|
||||||
|
GdbPlugin.PLUGIN_ID,
|
||||||
|
IGdbDebugPreferenceConstants.PREF_COMMAND_CUSTOM_TIMEOUTS,
|
||||||
|
"", //$NON-NLS-1$
|
||||||
|
null ) );
|
||||||
|
|
||||||
|
node.addPreferenceChangeListener( this );
|
||||||
|
|
||||||
|
fCommandControl.addCommandListener( this );
|
||||||
|
|
||||||
|
fTimerThread = new TimerThread( fCommandQueue, calculateWaitTimeout() );
|
||||||
|
fTimerThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
fTimerThread.shutdown();
|
||||||
|
fListeners.clear();
|
||||||
|
InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID ).removePreferenceChangeListener( this );
|
||||||
|
fCommandControl.removeCommandListener( this );
|
||||||
|
fCommandQueue.clear();
|
||||||
|
fCustomTimeouts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.dsf.debug.service.command.ICommandListener#commandQueued(org.eclipse.cdt.dsf.debug.service.command.ICommandToken)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void commandQueued( ICommandToken token ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.dsf.debug.service.command.ICommandListener#commandSent(org.eclipse.cdt.dsf.debug.service.command.ICommandToken)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void commandSent( ICommandToken token ) {
|
||||||
|
if ( !isTimeoutEnabled() )
|
||||||
|
return;
|
||||||
|
int commandTimeout = getTimeoutForCommand( token.getCommand() );
|
||||||
|
if ( DEBUG ) {
|
||||||
|
String commandText = token.getCommand().toString();
|
||||||
|
if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$
|
||||||
|
commandText = commandText.substring( 0, commandText.length() - 1 );
|
||||||
|
printDebugMessage( String.format( "Command '%s' sent, timeout = %d", commandText, Integer.valueOf( commandTimeout ) ) ); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
if ( commandTimeout == 0 )
|
||||||
|
// Skip commands with no timeout
|
||||||
|
return;
|
||||||
|
try {
|
||||||
|
fCommandQueue.put( new QueueEntry( System.currentTimeMillis(), token ) );
|
||||||
|
}
|
||||||
|
catch( InterruptedException e ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.dsf.debug.service.command.ICommandListener#commandRemoved(org.eclipse.cdt.dsf.debug.service.command.ICommandToken)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void commandRemoved( ICommandToken token ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.dsf.debug.service.command.ICommandListener#commandDone(org.eclipse.cdt.dsf.debug.service.command.ICommandToken, org.eclipse.cdt.dsf.debug.service.command.ICommandResult)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void commandDone( ICommandToken token, ICommandResult result ) {
|
||||||
|
if ( !isTimeoutEnabled() )
|
||||||
|
return;
|
||||||
|
fCommandQueue.remove( new QueueEntry( 0, token ) );
|
||||||
|
if ( DEBUG ) {
|
||||||
|
String commandText = token.getCommand().toString();
|
||||||
|
if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$
|
||||||
|
commandText = commandText.substring( 0, commandText.length() - 1 );
|
||||||
|
printDebugMessage( String.format( "Command '%s' is done", commandText ) ); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
// Reset the timestamp of the next command in the queue because
|
||||||
|
// regardless how long it has been in the queue GDB will start
|
||||||
|
// executing it only when the execution of the previous command
|
||||||
|
// is completed.
|
||||||
|
QueueEntry nextEntry = fCommandQueue.peek();
|
||||||
|
if ( nextEntry != null ) {
|
||||||
|
setTimeStamp( System.currentTimeMillis(), nextEntry );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void preferenceChange( PreferenceChangeEvent event ) {
|
||||||
|
String property = event.getKey();
|
||||||
|
if ( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT.equals( property ) ) {
|
||||||
|
// The new value is null when the timeout support is disabled.
|
||||||
|
if ( event.getNewValue() == null || !event.getNewValue().equals( event.getOldValue() ) ) {
|
||||||
|
fTimeoutEnabled = ( event.getNewValue() != null ) ?
|
||||||
|
Boolean.parseBoolean( event.getNewValue().toString() ) : Boolean.FALSE;
|
||||||
|
updateWaitTimeout();
|
||||||
|
fTimerThread.setTimerThreadState( ( fTimerThread.getWaitTimeout() > 0 ) ?
|
||||||
|
TimerThreadState.RUNNING : TimerThreadState.HALTED );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE.equals( property ) ) {
|
||||||
|
if ( event.getNewValue() == null || !event.getNewValue().equals( event.getOldValue() ) ) {
|
||||||
|
try {
|
||||||
|
fTimeout = ( event.getNewValue() != null ) ?
|
||||||
|
Integer.parseInt( event.getNewValue().toString() ) :
|
||||||
|
IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT;
|
||||||
|
updateWaitTimeout();
|
||||||
|
fTimerThread.setTimerThreadState( ( fTimerThread.getWaitTimeout() > 0 ) ?
|
||||||
|
TimerThreadState.RUNNING : TimerThreadState.HALTED );
|
||||||
|
}
|
||||||
|
catch( NumberFormatException e ) {
|
||||||
|
GdbPlugin.getDefault().getLog().log( new Status( IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Invlaid timeout value" ) ); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( IGdbDebugPreferenceConstants.PREF_COMMAND_CUSTOM_TIMEOUTS.equals( property ) ) {
|
||||||
|
if ( event.getNewValue() instanceof String ) {
|
||||||
|
fCustomTimeouts.initializeFromMemento( (String)event.getNewValue() );
|
||||||
|
}
|
||||||
|
else if ( event.getNewValue() == null ) {
|
||||||
|
fCustomTimeouts.clear();
|
||||||
|
}
|
||||||
|
updateWaitTimeout();
|
||||||
|
fTimerThread.setTimerThreadState( ( fTimerThread.getWaitTimeout() > 0 ) ?
|
||||||
|
TimerThreadState.RUNNING : TimerThreadState.HALTED );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getTimeoutForCommand( ICommand<? extends ICommandResult> command ) {
|
||||||
|
if ( !(command instanceof MICommand<?>) )
|
||||||
|
return 0;
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
Integer timeout = fCustomTimeouts.get( ((MICommand<? extends MIInfo>)command).getOperation() );
|
||||||
|
return ( timeout != null ) ? timeout.intValue() : fTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void processTimedOutCommand( ICommandToken token ) {
|
||||||
|
if ( DEBUG ) {
|
||||||
|
String commandText = token.getCommand().toString();
|
||||||
|
if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$
|
||||||
|
commandText = commandText.substring( 0, commandText.length() - 1 );
|
||||||
|
printDebugMessage( String.format( "Command '%s' is timed out", commandText ) ); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
for ( Object l : fListeners.getListeners() ) {
|
||||||
|
((ICommandTimeoutListener)l).commandTimedOut( token );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCommandTimeoutListener( ICommandTimeoutListener listener ) {
|
||||||
|
fListeners.add( listener );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeCommandTimeoutListener( ICommandTimeoutListener listener ) {
|
||||||
|
fListeners.remove( listener );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateWaitTimeout() {
|
||||||
|
fTimerThread.setWaitTimout( calculateWaitTimeout() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTimeoutEnabled() {
|
||||||
|
return fTimeoutEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printDebugMessage( String message ) {
|
||||||
|
System.out.println( String.format( "%s %s %s", GdbPlugin.getDebugTime(), TIMEOUT_TRACE_IDENTIFIER, message ) ); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
private int calculateWaitTimeout() {
|
||||||
|
int waitTimeout = 0;
|
||||||
|
if ( isTimeoutEnabled() ) {
|
||||||
|
waitTimeout = fTimeout;
|
||||||
|
int minCustomTimeout = Integer.MAX_VALUE;
|
||||||
|
for ( Integer t : fCustomTimeouts.values() ) {
|
||||||
|
if ( t.intValue() > 0 ) {
|
||||||
|
minCustomTimeout = Math.min( minCustomTimeout, t.intValue() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( minCustomTimeout > 0 ) {
|
||||||
|
waitTimeout = ( waitTimeout == 0 ) ?
|
||||||
|
minCustomTimeout : Math.min( waitTimeout, minCustomTimeout );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return waitTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTimeStamp( long currentTime, QueueEntry nextEntry ) {
|
||||||
|
if ( nextEntry != null ) {
|
||||||
|
nextEntry.fTimestamp = currentTime;
|
||||||
|
|
||||||
|
if ( DEBUG ) {
|
||||||
|
String commandText = nextEntry.fCommandToken.getCommand().toString();
|
||||||
|
if ( commandText.endsWith( "\n" ) ) //$NON-NLS-1$
|
||||||
|
commandText = commandText.substring( 0, commandText.length() - 1 );
|
||||||
|
printDebugMessage( String.format( "Setting the timestamp for command '%s' to %d", commandText, Long.valueOf( currentTime ) ) ); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
|
@ -874,6 +875,7 @@ public abstract class AbstractMIControl extends AbstractDsfService
|
||||||
}
|
}
|
||||||
|
|
||||||
void processMIOutput(String line) {
|
void processMIOutput(String line) {
|
||||||
|
|
||||||
MIParser.RecordType recordType = fMiParser.getRecordType(line);
|
MIParser.RecordType recordType = fMiParser.getRecordType(line);
|
||||||
|
|
||||||
if (recordType == MIParser.RecordType.ResultRecord) {
|
if (recordType == MIParser.RecordType.ResultRecord) {
|
||||||
|
@ -885,6 +887,7 @@ public abstract class AbstractMIControl extends AbstractDsfService
|
||||||
* some form of asynchronous notification. Or perhaps general IO.
|
* some form of asynchronous notification. Or perhaps general IO.
|
||||||
*/
|
*/
|
||||||
int id = rr.getToken();
|
int id = rr.getToken();
|
||||||
|
|
||||||
final CommandHandle commandHandle = fRxCommands.remove(id);
|
final CommandHandle commandHandle = fRxCommands.remove(id);
|
||||||
|
|
||||||
if (commandHandle != null) {
|
if (commandHandle != null) {
|
||||||
|
@ -1098,4 +1101,46 @@ public abstract class AbstractMIControl extends AbstractDsfService
|
||||||
fCurrentStackLevel = -1;
|
fCurrentStackLevel = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
@ConfinedToDsfExecutor("this.getExecutor()")
|
||||||
|
protected void commandFailed(ICommandToken token, int statusCode, String errorMessage) {
|
||||||
|
if ( !(token instanceof CommandHandle && token.getCommand() instanceof MICommand<?>) )
|
||||||
|
return;
|
||||||
|
final CommandHandle commandHandle = (CommandHandle)token;
|
||||||
|
Integer tokenId = commandHandle.getTokenId();
|
||||||
|
|
||||||
|
// If the timeout value is too small a command can be timed out but still processed by RxThread.
|
||||||
|
// To avoid processing it twice we need to remove it from the command list.
|
||||||
|
CommandHandle h = fRxCommands.remove(tokenId);
|
||||||
|
if (h == null)
|
||||||
|
// Command has already been processed by RxThread.
|
||||||
|
return;
|
||||||
|
|
||||||
|
MIConst value = new MIConst();
|
||||||
|
value.setCString(errorMessage);
|
||||||
|
MIResult result = new MIResult();
|
||||||
|
result.setVariable("msg"); //$NON-NLS-1$
|
||||||
|
result.setMIValue(value);
|
||||||
|
MIResultRecord resultRecord = new MIResultRecord();
|
||||||
|
resultRecord.setToken(tokenId.intValue());
|
||||||
|
resultRecord.setResultClass(MIResultRecord.ERROR);
|
||||||
|
resultRecord.setMIResults(new MIResult[] { result });
|
||||||
|
MIOutput miOutput = new MIOutput(resultRecord, new MIOOBRecord[0]);
|
||||||
|
|
||||||
|
final MIInfo info = commandHandle.getCommand().getResult(miOutput);
|
||||||
|
DataRequestMonitor<MIInfo> rm = commandHandle.getRequestMonitor();
|
||||||
|
|
||||||
|
if ( rm != null ) {
|
||||||
|
rm.setData(info);
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, statusCode, errorMessage, null));
|
||||||
|
rm.done();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now tell the generic listeners about it.
|
||||||
|
*/
|
||||||
|
processCommandDone(commandHandle, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,10 @@ public class BaseTestCase {
|
||||||
launchAttributes.put(key, value);
|
launchAttributes.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void removeLaunchAttribute(String key) {
|
||||||
|
launchAttributes.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
public static void setGlobalLaunchAttribute(String key, Object value) {
|
public static void setGlobalLaunchAttribute(String key, Object value) {
|
||||||
globalLaunchAttributes.put(key, value);
|
globalLaunchAttributes.put(key, value);
|
||||||
}
|
}
|
||||||
|
@ -206,6 +210,7 @@ public class BaseTestCase {
|
||||||
.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE);
|
.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE);
|
||||||
|
|
||||||
// First check if we should launch gdbserver in the case of a remote session
|
// First check if we should launch gdbserver in the case of a remote session
|
||||||
|
if (reallyLaunchGDBServer())
|
||||||
launchGdbServer();
|
launchGdbServer();
|
||||||
|
|
||||||
ILaunchManager launchMgr = DebugPlugin.getDefault().getLaunchManager();
|
ILaunchManager launchMgr = DebugPlugin.getDefault().getLaunchManager();
|
||||||
|
@ -332,4 +337,14 @@ public class BaseTestCase {
|
||||||
BaseTestCase.setLaunchAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME, "gdb." + version + (isWindows ? ".exe" : ""));
|
BaseTestCase.setLaunchAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME, "gdb." + version + (isWindows ? ".exe" : ""));
|
||||||
BaseTestCase.setLaunchAttribute(ATTR_DEBUG_SERVER_NAME, "gdbserver." + version + (isWindows ? ".exe" : ""));
|
BaseTestCase.setLaunchAttribute(ATTR_DEBUG_SERVER_NAME, "gdbserver." + version + (isWindows ? ".exe" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In some tests we need to start a gdbserver session without starting gdbserver.
|
||||||
|
* This method allows super classes of this class control the launch of gdbserver.
|
||||||
|
*
|
||||||
|
* @return whether gdbserver should be started
|
||||||
|
*/
|
||||||
|
protected boolean reallyLaunchGDBServer() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.junit.runners.Suite;
|
||||||
LaunchConfigurationAndRestartTest.class,
|
LaunchConfigurationAndRestartTest.class,
|
||||||
OperationsWhileTargetIsRunningTest.class,
|
OperationsWhileTargetIsRunningTest.class,
|
||||||
PostMortemCoreTest.class,
|
PostMortemCoreTest.class,
|
||||||
|
CommandTimeoutTest.class,
|
||||||
Suite_Sessionless_Tests.class,
|
Suite_Sessionless_Tests.class,
|
||||||
/* Add your suite class here */
|
/* Add your suite class here */
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012 Mentor Graphics 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:
|
||||||
|
* Mentor Graphics - Initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.tests.dsf.gdb.tests;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
|
import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner;
|
||||||
|
import org.eclipse.cdt.tests.dsf.gdb.framework.BaseTestCase;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
|
||||||
|
import org.eclipse.core.runtime.preferences.InstanceScope;
|
||||||
|
import org.eclipse.debug.core.DebugException;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@RunWith(BackgroundRunner.class)
|
||||||
|
public class CommandTimeoutTest extends BaseTestCase {
|
||||||
|
|
||||||
|
private static boolean fgTimeoutEnabled = false;
|
||||||
|
private static int fgTimeout = IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClassMethod() {
|
||||||
|
// Save the original values of the timeout-related preferences
|
||||||
|
fgTimeoutEnabled = Platform.getPreferencesService().getBoolean(
|
||||||
|
GdbPlugin.PLUGIN_ID,
|
||||||
|
IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT,
|
||||||
|
false,
|
||||||
|
null );
|
||||||
|
fgTimeout = Platform.getPreferencesService().getInt(
|
||||||
|
GdbPlugin.PLUGIN_ID,
|
||||||
|
IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE,
|
||||||
|
IGdbDebugPreferenceConstants.COMMAND_TIMEOUT_VALUE_DEFAULT,
|
||||||
|
null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
@Override
|
||||||
|
public void baseBeforeMethod() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
@Override
|
||||||
|
public void baseAfterMethod() throws Exception {
|
||||||
|
// Restore the timeout preferences
|
||||||
|
IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID );
|
||||||
|
node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, fgTimeoutEnabled );
|
||||||
|
node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, fgTimeout );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean reallyLaunchGDBServer() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables the timeout support and sets the timeout value to minimal - 1.
|
||||||
|
* Launch is expected to timeout on the first gdb command.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void firstCommandTimedOut() {
|
||||||
|
IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID );
|
||||||
|
node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, true );
|
||||||
|
node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, 1 );
|
||||||
|
|
||||||
|
try {
|
||||||
|
performLaunchAndTerminate();
|
||||||
|
Assert.fail( "Launch is expected to fail" );
|
||||||
|
}
|
||||||
|
catch( Exception e ) {
|
||||||
|
processException( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to connect to gdbserver without starting it.
|
||||||
|
* Launch is expected to timeout on "target-remote" command.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void remoteConnectionTimedOut() {
|
||||||
|
if ( !isRemoteSession() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
IEclipsePreferences node = InstanceScope.INSTANCE.getNode( GdbPlugin.PLUGIN_ID );
|
||||||
|
node.putBoolean( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT, true );
|
||||||
|
node.putInt( IGdbDebugPreferenceConstants.PREF_COMMAND_TIMEOUT_VALUE, 1000 );
|
||||||
|
|
||||||
|
try {
|
||||||
|
performLaunchAndTerminate();
|
||||||
|
Assert.fail( "Launch is expected to fail" );
|
||||||
|
}
|
||||||
|
catch( Exception e ) {
|
||||||
|
processException( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performLaunchAndTerminate() throws Exception {
|
||||||
|
super.baseBeforeMethod();
|
||||||
|
super.baseAfterMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given exception is an instance of {@link CoreException}
|
||||||
|
* with the status code 20100 which indicates that a gdb command has been timed out.
|
||||||
|
*/
|
||||||
|
private void processException( Exception e ) {
|
||||||
|
if ( e instanceof DebugException ) {
|
||||||
|
Throwable t = getExceptionCause( e );
|
||||||
|
Assert.assertTrue(
|
||||||
|
"Unexpected exception",
|
||||||
|
t instanceof CoreException && ((CoreException)t).getStatus().getCode() == 20100 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Assert.fail( "Unexpected exception type" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Throwable getExceptionCause(Throwable e) {
|
||||||
|
Throwable current = e;
|
||||||
|
while ( current instanceof CoreException ) {
|
||||||
|
Throwable t = ((CoreException)current).getCause();
|
||||||
|
if ( t == null )
|
||||||
|
break;
|
||||||
|
current = t;
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue