1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-19 15:05:36 +02:00

* Enabled correct API baseline (3.7) and fixed related API-check errors.

* Moved classes that are not part of the API to "internal" packages.
* Removed unnecessary classes.
* Simplified creation of checkers by providing alternative super class
and constructors.
This commit is contained in:
Alex Ruiz 2012-02-23 13:17:23 -08:00 committed by Sergey Prigogin
parent a631e47e43
commit b25c644007
33 changed files with 409 additions and 194 deletions

View file

@ -10,17 +10,18 @@
*******************************************************************************/
package org.eclipse.cdt.codan.internal.checkers;
import static java.util.Collections.singletonList;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser;
import org.eclipse.cdt.codan.core.externaltool.ConfigurationSettings;
import org.eclipse.cdt.codan.core.externaltool.InvocationParametersProvider;
import org.eclipse.cdt.codan.core.externaltool.SpaceDelimitedArgsSeparator;
import org.eclipse.cdt.codan.core.model.AbstractExternalToolBasedChecker;
import org.eclipse.cdt.codan.core.externaltool.InvocationParameters;
import org.eclipse.cdt.codan.core.model.IProblemLocation;
import org.eclipse.cdt.codan.ui.cxx.externaltool.CxxSupportedResourceVerifier;
import org.eclipse.cdt.codan.ui.externaltool.CommandInvoker;
import org.eclipse.cdt.codan.ui.cxx.externaltool.AbstractCxxExternalToolBasedChecker;
/**
* Checker that invokes <a href="http://cppcheck.sourceforge.net/">Cppcheck</a> when a C/C++ is
@ -28,7 +29,7 @@ import org.eclipse.cdt.codan.ui.externaltool.CommandInvoker;
*
* @author alruiz@google.com (Alex Ruiz)
*/
public class CppcheckChecker extends AbstractExternalToolBasedChecker {
public class CppcheckChecker extends AbstractCxxExternalToolBasedChecker {
private static final String TOOL_NAME = "Cppcheck"; //$NON-NLS-1$
private static final String EXECUTABLE_NAME = "cppcheck"; //$NON-NLS-1$
private static final String DEFAULT_ARGS = ""; //$NON-NLS-1$
@ -51,10 +52,7 @@ public class CppcheckChecker extends AbstractExternalToolBasedChecker {
}
public CppcheckChecker() {
super(new InvocationParametersProvider(), new CxxSupportedResourceVerifier(),
new SpaceDelimitedArgsSeparator(), new CommandInvoker(),
new CppcheckOutputParserFactory(),
new ConfigurationSettings(TOOL_NAME, new File(EXECUTABLE_NAME), DEFAULT_ARGS));
super(new ConfigurationSettings(TOOL_NAME, new File(EXECUTABLE_NAME), DEFAULT_ARGS, false));
}
@Override
@ -70,4 +68,10 @@ public class CppcheckChecker extends AbstractExternalToolBasedChecker {
protected String getReferenceProblemId() {
return ERROR_PROBLEM_ID;
}
@Override
protected List<AbstractOutputParser> createParsers(InvocationParameters parameters) {
AbstractOutputParser parser = new CppcheckOutputParser(parameters, this);
return singletonList(parser);
}
}

View file

@ -14,7 +14,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.codan.core.CodanRuntime;
import org.eclipse.cdt.codan.core.externaltool.IOutputParser;
import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser;
import org.eclipse.cdt.codan.core.externaltool.IProblemDisplay;
import org.eclipse.cdt.codan.core.externaltool.InvocationParameters;
import org.eclipse.cdt.codan.core.model.IProblemLocation;
@ -26,7 +26,7 @@ import org.eclipse.core.resources.IFile;
*
* @author alruiz@google.com (Alex Ruiz)
*/
class CppcheckOutputParser implements IOutputParser {
class CppcheckOutputParser extends AbstractOutputParser {
// the pattern for parsing the message is:
//
// [/src/HelloWorld.cpp:19]: (style) The scope of the variable 'i' can be reduced

View file

@ -1,32 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* 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 - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.checkers;
import static java.util.Collections.singletonList;
import java.util.List;
import org.eclipse.cdt.codan.core.externaltool.IOutputParser;
import org.eclipse.cdt.codan.core.externaltool.IOutputParserFactory;
import org.eclipse.cdt.codan.core.externaltool.IProblemDisplay;
import org.eclipse.cdt.codan.core.externaltool.InvocationParameters;
/**
* @author alruiz@google.com (Alex Ruiz)
*/
class CppcheckOutputParserFactory implements IOutputParserFactory {
@Override
public List<IOutputParser> createParsers(InvocationParameters parameters,
IProblemDisplay problemDisplay) {
IOutputParser parser = new CppcheckOutputParser(parameters, problemDisplay);
return singletonList(parser);
}
}

View file

@ -0,0 +1,127 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* 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 - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.core.externaltool;
import static org.junit.Assert.assertArrayEquals;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.codan.core.externaltool.ConfigurationSettings;
import org.eclipse.cdt.codan.core.externaltool.IArgsSeparator;
import org.eclipse.cdt.codan.core.externaltool.ICommandLauncher;
import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser;
import org.eclipse.cdt.codan.core.externaltool.InvocationFailure;
import org.eclipse.cdt.codan.core.externaltool.InvocationParameters;
import org.eclipse.cdt.codan.core.externaltool.SpaceDelimitedArgsSeparator;
import org.eclipse.cdt.codan.core.param.BasicProblemPreference;
import org.eclipse.cdt.codan.core.param.MapProblemPreference;
import org.eclipse.cdt.codan.core.test.CodanTestCase;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
/**
* Tests for <code>{@link ExternalToolInvoker}</code>.
*
* @author alruiz@google.com (Alex Ruiz)
*/
@SuppressWarnings("nls")
public class ExternalToolInvokerTest extends CodanTestCase {
private static final String EXTERNAL_TOOL_NAME = "TestTool";
private ConfigurationSettings configurationSettings;
private IArgsSeparator argsSeparator;
private List<AbstractOutputParser> parsers;
private CommandLauncherStub commandLauncher;
private ExternalToolInvoker externalToolInvoker;
@Override
public void setUp() throws Exception {
super.setUp();
createConfigurationSettings();
argsSeparator = new SpaceDelimitedArgsSeparator();
parsers = new ArrayList<AbstractOutputParser>();
commandLauncher = new CommandLauncherStub();
externalToolInvoker = new ExternalToolInvoker(commandLauncher);
}
private void createConfigurationSettings() {
configurationSettings = new ConfigurationSettings(EXTERNAL_TOOL_NAME, new File("testtool"),
"", false);
// Update current value of ConfigurationSettings from preferences.
MapProblemPreference preferences = createPreferences(new File("usr/local/testtool"),
"--debug=true --include=all", true);
configurationSettings.updateValuesFrom(preferences);
}
private MapProblemPreference createPreferences(File path, String args,
boolean shouldDisplayOutput) {
MapProblemPreference preferences = new MapProblemPreference();
preferences.addChildDescriptor(new BasicProblemPreference("externalToolPath", "Path"));
preferences.addChildDescriptor(new BasicProblemPreference("externalToolArgs", "Args"));
preferences.addChildDescriptor(new BasicProblemPreference("externalToolShouldDisplayOutput",
"Should Display Output"));
preferences.setChildValue("externalToolPath", path);
preferences.setChildValue("externalToolArgs", args);
preferences.setChildValue("externalToolShouldDisplayOutput", shouldDisplayOutput);
return preferences;
}
@Override
public boolean isCpp() {
return true;
}
// class C {
// };
public void testCommandLauncherGetsCalledCorrectly() throws Throwable {
loadcode(getAboveComment());
InvocationParameters parameters = new InvocationParameters(currentIFile, currentIFile,
currentIFile.getLocation().toOSString(), cproject.getProject().getLocation());
externalToolInvoker.invoke(parameters, configurationSettings, argsSeparator, parsers);
assertSame(cproject.getProject(), commandLauncher.project);
assertEquals(EXTERNAL_TOOL_NAME, commandLauncher.externalToolName);
String expectedExecutablePath = configurationSettings.getPath().getValue().toString();
assertEquals(expectedExecutablePath, commandLauncher.executablePath.toOSString());
String[] expectedArgs = { parameters.getActualFilePath(), "--debug=true", "--include=all" };
assertArrayEquals(expectedArgs, commandLauncher.args);
assertEquals(parameters.getWorkingDirectory(), commandLauncher.workingDirectory);
assertEquals(configurationSettings.getShouldDisplayOutput().getValue().booleanValue(),
commandLauncher.shouldDisplayOutput);
assertSame(parsers, commandLauncher.parsers);
}
private static class CommandLauncherStub implements ICommandLauncher {
IProject project;
String externalToolName;
IPath executablePath;
String[] args;
IPath workingDirectory;
boolean shouldDisplayOutput;
List<AbstractOutputParser> parsers;
@Override
public void buildAndLaunchCommand(IProject project, String externalToolName,
IPath executablePath, String[] args, IPath workingDirectory,
boolean shouldDisplayOutput, List<AbstractOutputParser> parsers) throws InvocationFailure,
Throwable {
this.project = project;
this.externalToolName = externalToolName;
this.executablePath = executablePath;
this.args = args;
this.workingDirectory = workingDirectory;
this.shouldDisplayOutput = shouldDisplayOutput;
this.parsers = parsers;
}
}
}

View file

@ -20,4 +20,5 @@ Export-Package: org.eclipse.cdt.codan.core,
org.eclipse.cdt.codan.core.test,
org.eclipse.cdt.codan.ui",
org.eclipse.cdt.codan.internal.core.cfg;x-friends:="org.eclipse.cdt.codan.core.cxx",
org.eclipse.cdt.codan.internal.core.externaltool,
org.eclipse.cdt.codan.internal.core.model;x-friends:="org.eclipse.cdt.codan.core.cxx,org.eclipse.cdt.codan.core.test,org.eclipse.cdt.codan.ui"

View file

@ -14,8 +14,10 @@ package org.eclipse.cdt.codan.core.externaltool;
* Parses the output of an external tool.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public interface IOutputParser {
public abstract class AbstractOutputParser {
/**
* Parses one line of output. Implementations are free to create markers from the information
* retrieved from the parsed output.
@ -24,11 +26,11 @@ public interface IOutputParser {
* @throws InvocationFailure if the output indicates that the invocation of the external tool
* failed.
*/
boolean parse(String line) throws InvocationFailure;
public abstract boolean parse(String line) throws InvocationFailure;
/**
* Resets the value of this parser, usually after the execution of the external tool is
* finished.
*/
void reset();
public abstract void reset();
}

View file

@ -10,18 +10,19 @@
*******************************************************************************/
package org.eclipse.cdt.codan.core.externaltool;
import static org.eclipse.cdt.codan.core.externaltool.Messages.ConfigurationSettings_args_format;
import static org.eclipse.cdt.codan.core.externaltool.Messages.ConfigurationSettings_path_format;
import static org.eclipse.cdt.codan.core.externaltool.Messages.ConfigurationSettings_should_display_output;
import java.io.File;
import org.eclipse.cdt.codan.core.param.MapProblemPreference;
import org.eclipse.cdt.codan.internal.core.externaltool.ArgsSetting;
import org.eclipse.cdt.codan.internal.core.externaltool.PathSetting;
import org.eclipse.cdt.codan.internal.core.externaltool.ShouldDisplayOutputSetting;
/**
* User-configurable external tool settings.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class ConfigurationSettings {
private final PathSetting path;
@ -31,38 +32,18 @@ public class ConfigurationSettings {
/**
* Constructor.
* <p>
* <strong>Note:</strong> this constructor uses {@code false} as the default value of the
* <code>{@link ShouldDisplayOutputSetting}</code> to create.
* </p>
* @param externalToolName the name of the external tool, to be displayed to the user.
* @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;
String pathLabel = String.format(ConfigurationSettings_path_format, externalToolName);
this.path = new PathSetting(pathLabel, defaultPath);
String argsLabel = String.format(ConfigurationSettings_args_format, externalToolName);
this.args = new ArgsSetting(argsLabel, defaultArgs);
String shouldDisplayOutputLabel = ConfigurationSettings_should_display_output;
this.shouldDisplayOutput = new ShouldDisplayOutputSetting(shouldDisplayOutputLabel, false);
}
/**
* Constructor.
* @param externalToolName the name of the external tool, to be displayed to the user.
* @param path specifies the path and name of the external tool to invoke.
* @param args specifies the arguments to pass when invoking the external tool.
* @param shouldDisplayOutput specifies whether the output of the external tools should be
* @param defaultShouldDisplayOutput indicates whether output of an external tool should be
* displayed in an Eclipse console.
*/
public ConfigurationSettings(String externalToolName, PathSetting path, ArgsSetting args,
ShouldDisplayOutputSetting shouldDisplayOutput) {
public ConfigurationSettings(String externalToolName, File defaultPath, String defaultArgs,
boolean defaultShouldDisplayOutput) {
this.externalToolName = externalToolName;
this.path = path;
this.args = args;
this.shouldDisplayOutput = shouldDisplayOutput;
this.path = new PathSetting(externalToolName, defaultPath);
this.args = new ArgsSetting(externalToolName, defaultArgs);
this.shouldDisplayOutput = new ShouldDisplayOutputSetting(defaultShouldDisplayOutput);
}
/**
@ -77,7 +58,7 @@ public class ConfigurationSettings {
* 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 PathSetting getPath() {
public SingleConfigurationSetting<File> getPath() {
return path;
}
@ -85,7 +66,7 @@ public class ConfigurationSettings {
* 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 ArgsSetting getArgs() {
public SingleConfigurationSetting<String> getArgs() {
return args;
}
@ -95,7 +76,7 @@ public class ConfigurationSettings {
* @return the shouldDisplayOutput the setting that specifies whether the output of the external
* tools should be displayed in an Eclipse console.
*/
public ShouldDisplayOutputSetting getShouldDisplayOutput() {
public SingleConfigurationSetting<Boolean> getShouldDisplayOutput() {
return shouldDisplayOutput;
}

View file

@ -11,20 +11,19 @@
package org.eclipse.cdt.codan.core.externaltool;
/**
* Parses and separates the value of an <code>{@link ArgsSetting}</code> into an array of
* {@code String}s.
* Parses a given {@code String} containing the arguments to pass to an external tool and separates
* them into individual values.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public interface IArgsSeparator {
/**
* Indicates that there are no arguments to pass to the external tool executable.
*/
String[] NO_ARGS = new String[0];
/**
* Parses and separates the given value.
* @param args contains the arguments to pass to the external tool executable.
* Parses a given {@code String} containing the arguments to pass to an external tool and
* separates them into individual values.
* @param args contains the arguments to pass to the external tool
* executable.
* @return the separated argument values.
*/
String[] separateArgs(String args);

View file

@ -16,10 +16,13 @@ import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
/**
* Builds and launches the command necessary to invoke an external tool.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public interface ICommandInvoker {
public interface ICommandLauncher {
/**
* Builds and launches the command necessary to invoke an external tool.
* @param project the current project.
@ -35,5 +38,5 @@ public interface ICommandInvoker {
*/
void buildAndLaunchCommand(IProject project, String externalToolName, IPath executablePath,
String[] args, IPath workingDirectory, boolean shouldDisplayOutput,
List<IOutputParser> parsers) throws InvocationFailure, Throwable;
List<AbstractOutputParser> parsers) throws InvocationFailure, Throwable;
}

View file

@ -16,6 +16,8 @@ import org.eclipse.core.resources.IResource;
* Provides the parameters to pass when invoking an external tool.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public interface IInvocationParametersProvider {
/**

View file

@ -1,29 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* 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 - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.externaltool;
import java.util.List;
/**
* Factory of instances of <code>{@link IOutputParser}</code>.
*
* @author alruiz@google.com (Alex Ruiz)
*/
public interface IOutputParserFactory {
/**
* Creates instances of <code>{@link IOutputParser}</code>.
* @param parameters the parameters to pass when invoking an external tool.
* @param problemDisplay displays problems found by the external tool.
* @return the created parsers.
*/
List<IOutputParser> createParsers(InvocationParameters parameters,
IProblemDisplay problemDisplay);
}

View file

@ -16,6 +16,8 @@ import org.eclipse.cdt.codan.core.model.IProblemLocation;
* Reports problems found in code, reported by an external tool.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public interface IProblemDisplay {
/**

View file

@ -17,22 +17,26 @@ import org.eclipse.core.resources.IResource;
* Verifies that a <code>{@link IResource}</code> can be processed by an external tool.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public interface ISupportedResourceVerifier {
/**
* Indicates whether the external tool is capable of processing the given
* <code>{@link IResource}</code>.
* <p>
* The minimum requirements that the given {@code IResource} should satisfy are:
* The minimum requirements that the given {@code IResource} should satisfy
* are:
* <ul>
* <li>should be an <code>{@link IFile}</code></li>
* <li>should be displayed in the current active editor</li>
* <li>should not have any unsaved changes</li>
* </ul>
* </p>
*
* @param resource the given {@code IResource}.
* @return {@code true} if the external tool is capable of processing the given file,
* {@code false} otherwise.
* @return {@code true} if the external tool is capable of processing the
* given file, {@code false} otherwise.
*/
boolean isSupported(IResource resource);
}

View file

@ -14,6 +14,8 @@ package org.eclipse.cdt.codan.core.externaltool;
* Indicates that invocation of an external tool failed.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class InvocationFailure extends Exception {
private static final long serialVersionUID = 1L;

View file

@ -17,6 +17,8 @@ import org.eclipse.core.runtime.IPath;
* Parameters to pass when invoking an external tool.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class InvocationParameters {
private final IResource originalFile;

View file

@ -16,6 +16,8 @@ import org.eclipse.core.resources.IResource;
* Default implementation of <code>{@link InvocationParameters}</code>
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class InvocationParametersProvider implements IInvocationParametersProvider {
/**

View file

@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.cdt.codan.core.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;
@ -18,6 +19,8 @@ import org.eclipse.cdt.codan.core.param.MapProblemPreference;
* @param <T> the type of the value this setting stores.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class SingleConfigurationSetting<T> {
private final IProblemPreferenceDescriptor descriptor;
@ -70,7 +73,9 @@ public class SingleConfigurationSetting<T> {
* by this setting.
*/
public void updateValue(MapProblemPreference preferences) {
Object o = preferences.getChildValue(descriptor.getKey());
value = valueType.cast(o);
IProblemPreference childDescriptor = preferences.getChildDescriptor(descriptor.getKey());
if (childDescriptor != null) {
value = valueType.cast(childDescriptor.getValue());
}
}
}

View file

@ -13,11 +13,15 @@ package org.eclipse.cdt.codan.core.externaltool;
import java.util.regex.Pattern;
/**
* Separates the value of an <code>{@link ArgsSetting}</code> using an empty space as delimiter.
* Default implementation of <code>{@link IArgsSeparator}</code> that uses an empty space as
* the delimiter to separate the arguments to pass to an external tool.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class SpaceDelimitedArgsSeparator implements IArgsSeparator {
private static final String[] NO_ARGS = new String[0];
private static final Pattern EMPTY_SPACE_PATTERN = Pattern.compile("\\s+"); //$NON-NLS-1$
/**

View file

@ -5,12 +5,11 @@ package org.eclipse.cdt.codan.core.model;
import java.util.List;
import org.eclipse.cdt.codan.core.CodanCorePlugin;
import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser;
import org.eclipse.cdt.codan.core.externaltool.ConfigurationSettings;
import org.eclipse.cdt.codan.core.externaltool.IArgsSeparator;
import org.eclipse.cdt.codan.core.externaltool.ICommandInvoker;
import org.eclipse.cdt.codan.core.externaltool.ICommandLauncher;
import org.eclipse.cdt.codan.core.externaltool.IInvocationParametersProvider;
import org.eclipse.cdt.codan.core.externaltool.IOutputParser;
import org.eclipse.cdt.codan.core.externaltool.IOutputParserFactory;
import org.eclipse.cdt.codan.core.externaltool.IProblemDisplay;
import org.eclipse.cdt.codan.core.externaltool.ISupportedResourceVerifier;
import org.eclipse.cdt.codan.core.externaltool.InvocationFailure;
@ -32,10 +31,12 @@ import org.eclipse.core.resources.IResource;
* <li>not have any unsaved changes</li>
* </ol>
* </p>
* By default, implementations of this checker are not enable to run while the user types, since
* By default, implementations of this checker are not allowed to run while the user types, since
* external tools cannot see unsaved changes.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWithProblemPreferences
implements IProblemDisplay {
@ -44,7 +45,6 @@ public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWi
private final IInvocationParametersProvider parametersProvider;
private final ISupportedResourceVerifier supportedResourceVerifier;
private final IArgsSeparator argsSeparator;
private final IOutputParserFactory outputParserFactory;
private final ConfigurationSettings configurationSettings;
private final ExternalToolInvoker externalToolInvoker;
private final RootProblemPreference preferences;
@ -56,20 +56,17 @@ public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWi
* external tool.
* @param argsSeparator separates the arguments to pass to the external tool executable. These
* arguments are stored in a single {@code String}.
* @param commandInvoker builds and launches the command necessary to invoke the external tool.
* @param outputParserFactory creates parsers for the output of the external tool.
* @param commandLauncher builds and launches the command necessary to invoke the external tool.
* @param configurationSettings user-configurable external tool configuration settings.
*/
public AbstractExternalToolBasedChecker(IInvocationParametersProvider parametersProvider,
ISupportedResourceVerifier supportedResourceVerifier, IArgsSeparator argsSeparator,
ICommandInvoker commandInvoker, IOutputParserFactory outputParserFactory,
ConfigurationSettings configurationSettings) {
ICommandLauncher commandLauncher, ConfigurationSettings configurationSettings) {
this.parametersProvider = parametersProvider;
this.supportedResourceVerifier = supportedResourceVerifier;
this.argsSeparator = argsSeparator;
this.outputParserFactory = outputParserFactory;
this.configurationSettings = configurationSettings;
externalToolInvoker = new ExternalToolInvoker(commandInvoker);
externalToolInvoker = new ExternalToolInvoker(commandLauncher);
preferences = new SharedRootProblemPreference();
}
@ -118,7 +115,7 @@ public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWi
private void invokeExternalTool(InvocationParameters parameters) throws Throwable {
updateConfigurationSettingsFromPreferences(parameters.getActualFile());
List<IOutputParser> parsers = outputParserFactory.createParsers(parameters, this);
List<AbstractOutputParser> parsers = createParsers(parameters);
try {
externalToolInvoker.invoke(parameters, configurationSettings, argsSeparator, parsers);
} catch (InvocationFailure error) {
@ -132,6 +129,12 @@ public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWi
configurationSettings.updateValuesFrom(preferences);
}
/**
* Creates instances of <code>{@link AbstractOutputParser}</code>.
* @param parameters the parameters to pass when invoking an external tool.
*/
protected abstract List<AbstractOutputParser> createParsers(InvocationParameters parameters);
/**
* Handles a failure reported when invoking the external tool. This implementation simply
* logs the failure.

View file

@ -10,11 +10,12 @@
*******************************************************************************/
package org.eclipse.cdt.codan.core.param;
/**
* Preferences that can be shared among several problems.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class SharedRootProblemPreference extends RootProblemPreference {
@Override

View file

@ -8,27 +8,37 @@
* Contributors:
* Alex Ruiz - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.externaltool;
package org.eclipse.cdt.codan.internal.core.externaltool;
import static org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType.TYPE_STRING;
import static org.eclipse.cdt.codan.internal.core.externaltool.Messages.ConfigurationSettings_args_format;
import org.eclipse.cdt.codan.core.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}.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class ArgsSetting extends SingleConfigurationSetting<String> {
private static final String KEY = "externalToolArgs"; //$NON-NLS-1$
/**
* Constructor.
* @param label the label to be displayed in the UI.
* @param externalToolName the name of the external tool, to be displayed to the user.
* @param defaultValue the default value of the setting.
*/
public ArgsSetting(String label, String defaultValue) {
super(new BasicProblemPreference(KEY, label, TYPE_STRING), defaultValue, String.class);
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);
}
}

View file

@ -15,8 +15,8 @@ import java.util.List;
import org.eclipse.cdt.codan.core.externaltool.ConfigurationSettings;
import org.eclipse.cdt.codan.core.externaltool.IArgsSeparator;
import org.eclipse.cdt.codan.core.externaltool.ICommandInvoker;
import org.eclipse.cdt.codan.core.externaltool.IOutputParser;
import org.eclipse.cdt.codan.core.externaltool.ICommandLauncher;
import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser;
import org.eclipse.cdt.codan.core.externaltool.InvocationFailure;
import org.eclipse.cdt.codan.core.externaltool.InvocationParameters;
import org.eclipse.core.resources.IProject;
@ -27,38 +27,43 @@ import org.eclipse.core.runtime.Path;
* Invokes an external tool to perform checks on a single file.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class ExternalToolInvoker {
private final ICommandInvoker commandInvoker;
private final ICommandLauncher commandLauncher;
/**
* Constructor.
* @param commandInvoker builds and launches the command necessary to invoke the external tool.
*
* @param commandLauncher builds and launches the command necessary to
* invoke the external tool.
*/
public ExternalToolInvoker(ICommandInvoker commandInvoker) {
this.commandInvoker = commandInvoker;
public ExternalToolInvoker(ICommandLauncher commandLauncher) {
this.commandLauncher = commandLauncher;
}
/**
* Invokes an external tool.
*
* @param parameters the parameters to pass to the external tool executable.
* @param configurationSettings 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 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 reports that it cannot be executed.
* @throws InvocationFailure if the external tool reports that it cannot be
* executed.
* @throws Throwable if the external tool cannot be launched.
*/
public void invoke(InvocationParameters parameters, ConfigurationSettings configurationSettings,
IArgsSeparator argsSeparator, List<IOutputParser> parsers) throws InvocationFailure,
Throwable {
public void invoke(InvocationParameters parameters, ConfigurationSettings configurationSettings, IArgsSeparator argsSeparator,
List<AbstractOutputParser> parsers) throws InvocationFailure, Throwable {
IPath executablePath = executablePath(configurationSettings);
String[] args = argsToPass(parameters, configurationSettings, argsSeparator);
boolean shouldDisplayOutput = configurationSettings.getShouldDisplayOutput().getValue();
IProject project = parameters.getActualFile().getProject();
try {
commandInvoker.buildAndLaunchCommand(project,
configurationSettings.getExternalToolName(), executablePath, args,
commandLauncher.buildAndLaunchCommand(project, configurationSettings.getExternalToolName(), executablePath, args,
parameters.getWorkingDirectory(), shouldDisplayOutput, parsers);
} finally {
reset(parsers);
@ -70,21 +75,20 @@ public class ExternalToolInvoker {
return new Path(executablePath.toString());
}
private String[] argsToPass(InvocationParameters parameters,
ConfigurationSettings configurationSettings, IArgsSeparator argsSeparator) {
private String[] argsToPass(InvocationParameters parameters, ConfigurationSettings configurationSettings, IArgsSeparator argsSeparator) {
String[] configuredArgs = configuredArgs(configurationSettings, argsSeparator);
String actualFilePath = parameters.getActualFilePath();
return addFilePathToArgs(actualFilePath, configuredArgs);
}
private String[] configuredArgs(ConfigurationSettings configurationSettings,
IArgsSeparator argsSeparator) {
private String[] configuredArgs(ConfigurationSettings configurationSettings, IArgsSeparator argsSeparator) {
String args = configurationSettings.getArgs().getValue();
return argsSeparator.separateArgs(args);
}
private String[] addFilePathToArgs(String actualFilePath, String[] configuredArgs) {
int argCount = configuredArgs.length;
// TODO (alruiz) use array copy.
String[] allArgs = new String[argCount + 1];
// add file to process as the first argument
allArgs[0] = actualFilePath;
@ -94,8 +98,8 @@ public class ExternalToolInvoker {
return allArgs;
}
private void reset(List<IOutputParser> parsers) {
for (IOutputParser parser : parsers) {
private void reset(List<AbstractOutputParser> parsers) {
for (AbstractOutputParser parser : parsers) {
parser.reset();
}
}

View file

@ -8,12 +8,14 @@
* Contributors:
* Alex Ruiz - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.externaltool;
package org.eclipse.cdt.codan.internal.core.externaltool;
import org.eclipse.osgi.util.NLS;
/**
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
@SuppressWarnings("javadoc")
public class Messages extends NLS {

View file

@ -8,28 +8,38 @@
* Contributors:
* Alex Ruiz - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.externaltool;
package org.eclipse.cdt.codan.internal.core.externaltool;
import static org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType.TYPE_FILE;
import static org.eclipse.cdt.codan.internal.core.externaltool.Messages.ConfigurationSettings_path_format;
import java.io.File;
import org.eclipse.cdt.codan.core.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.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class PathSetting extends SingleConfigurationSetting<File> {
private static final String KEY = "externalToolPath"; //$NON-NLS-1$
/**
* Constructor.
* @param label the label to be displayed in the UI.
* @param externalToolName the name of the external tool, to be displayed to the user.
* @param defaultValue the default value of the setting.
*/
public PathSetting(String label, File defaultValue) {
super(new BasicProblemPreference(KEY, label, TYPE_FILE), defaultValue, File.class);
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);
}
}

View file

@ -8,27 +8,36 @@
* Contributors:
* Alex Ruiz - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.externaltool;
package org.eclipse.cdt.codan.internal.core.externaltool;
import static org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType.TYPE_BOOLEAN;
import static org.eclipse.cdt.codan.internal.core.externaltool.Messages.ConfigurationSettings_should_display_output;
import org.eclipse.cdt.codan.core.externaltool.SingleConfigurationSetting;
import org.eclipse.cdt.codan.core.param.BasicProblemPreference;
import org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor;
/**
* User-configurable setting that specifies whether the output of an external tool should be
* displayed in an Eclipse console.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class ShouldDisplayOutputSetting extends SingleConfigurationSetting<Boolean> {
private static final String KEY = "externalToolShouldDisplayOutput"; //$NON-NLS-1$
/**
* Constructor.
* @param label the label to be displayed in the UI.
* @param defaultValue the default value of the setting.
*/
public ShouldDisplayOutputSetting(String label, boolean defaultValue) {
super(new BasicProblemPreference(KEY, label, TYPE_BOOLEAN), defaultValue, Boolean.class);
public ShouldDisplayOutputSetting(boolean defaultValue) {
super(newPreferenceDescriptor(), defaultValue, Boolean.class);
}
private static IProblemPreferenceDescriptor newPreferenceDescriptor() {
String label = ConfigurationSettings_should_display_output;
return new BasicProblemPreference(KEY, label, TYPE_BOOLEAN);
}
}

View file

@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* 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 - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.ui.cxx.externaltool;
import org.eclipse.cdt.codan.core.externaltool.ConfigurationSettings;
import org.eclipse.cdt.codan.core.externaltool.IArgsSeparator;
import org.eclipse.cdt.codan.core.externaltool.IInvocationParametersProvider;
import org.eclipse.cdt.codan.core.externaltool.ISupportedResourceVerifier;
import org.eclipse.cdt.codan.core.externaltool.InvocationParametersProvider;
import org.eclipse.cdt.codan.core.externaltool.SpaceDelimitedArgsSeparator;
import org.eclipse.cdt.codan.core.model.AbstractExternalToolBasedChecker;
import org.eclipse.cdt.codan.ui.externaltool.CommandLauncher;
/**
* Base class for checkers that invoke external command-line tools to perform code checking
* on C++ files.
* <p>
* A file, to be processed by this type of checker, must:
* <ol>
* <li>a C++ file</li>
* <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.
*
* @author alruiz@google.com (Alex Ruiz)
*/
public abstract class AbstractCxxExternalToolBasedChecker extends AbstractExternalToolBasedChecker {
/**
* Constructor
* @param configurationSettings user-configurable external tool configuration settings.
*/
public AbstractCxxExternalToolBasedChecker(ConfigurationSettings configurationSettings) {
this(new InvocationParametersProvider(), new CxxSupportedResourceVerifier(),
new SpaceDelimitedArgsSeparator(), configurationSettings);
}
/**
* Constructor.
* @param parametersProvider provides the parameters to pass when invoking the external tool.
* @param supportedResourceVerifier indicates whether a resource can be processed by 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 configurationSettings user-configurable external tool configuration settings.
*/
public AbstractCxxExternalToolBasedChecker(IInvocationParametersProvider parametersProvider,
ISupportedResourceVerifier supportedResourceVerifier, IArgsSeparator argsSeparator,
ConfigurationSettings configurationSettings) {
super(parametersProvider, supportedResourceVerifier, argsSeparator, new CommandLauncher(),
configurationSettings);
}
}

View file

@ -24,9 +24,12 @@ import org.eclipse.ui.editors.text.TextEditor;
* @author alruiz@google.com (Alex Ruiz)
*/
@SuppressWarnings("restriction") // CEditor is internal API
final class CEditors {
static TextEditor activeCEditor() {
public final class CEditors {
/**
* Finds the current {@code CEditor}.
* @return the current {@code CEditor}, or {@code null} if one cannot be found.
*/
public static TextEditor activeCEditor() {
IWorkbench workbench = PlatformUI.getWorkbench();
for (IWorkbenchWindow w : workbench.getWorkbenchWindows()) {
IWorkbenchPage activePage = w.getActivePage();

View file

@ -20,11 +20,11 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.ui.editors.text.TextEditor;
/**
* Implemenation of <code>{@link ISupportedResourceVerifier}</code> for C/C++ files.
* Implementation of <code>{@link ISupportedResourceVerifier}</code> for C/C++ files.
*
* @author alruiz@google.com (Alex Ruiz)
*/
public class CxxSupportedResourceVerifier implements ISupportedResourceVerifier {
class CxxSupportedResourceVerifier implements ISupportedResourceVerifier {
/**
* Indicates whether the external tool is capable of processing the given
* <code>{@link IResource}</code>.

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.eclipse.cdt.codan.ui; singleton:=true
Bundle-Version: 2.0.1.qualifier
Bundle-Version: 2.1.0.qualifier
Bundle-Activator: org.eclipse.cdt.codan.internal.ui.CodanUIActivator
Bundle-Vendor: %Bundle-Vendor
Require-Bundle: org.eclipse.ui,

View file

@ -160,6 +160,7 @@ public class CodanEditorUtility {
/**
* Returns the active workbench page.
* @return the active workbench page, or {@code null} if none can be found.
* @since 2.1
*/
public static IWorkbenchPage getActivePage() {
IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();

View file

@ -17,26 +17,28 @@ import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
import org.eclipse.cdt.codan.core.externaltool.ICommandInvoker;
import org.eclipse.cdt.codan.core.externaltool.IOutputParser;
import org.eclipse.cdt.codan.core.externaltool.ICommandLauncher;
import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser;
import org.eclipse.cdt.codan.core.externaltool.InvocationFailure;
import org.eclipse.cdt.codan.internal.ui.CodanUIActivator;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.ui.PartInitException;
/**
* Invokes an external tool command.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @since 2.1
*/
public class CommandInvoker implements ICommandInvoker {
public class CommandLauncher implements ICommandLauncher {
private static final String[] ENVIRONMENT_VARIABLE_SETTINGS = {};
private ConsolePrinterFactory consolePrinterFactory = new ConsolePrinterFactory();
@Override
public void buildAndLaunchCommand(IProject project, String externalToolName,
IPath executablePath, String[] args, IPath workingDirectory, boolean shouldDisplayOutput,
List<IOutputParser> parsers) throws InvocationFailure, Throwable {
List<AbstractOutputParser> parsers) throws InvocationFailure, Throwable {
ConsolePrinter consolePrinter = consolePrinter(externalToolName, shouldDisplayOutput);
String command = buildCommand(executablePath, args);
Process process = null;
@ -60,14 +62,7 @@ public class CommandInvoker implements ICommandInvoker {
}
private ConsolePrinter consolePrinter(String externalToolName, boolean shouldDisplayOutput) {
if (shouldDisplayOutput) {
try {
return ConsolePrinterImpl.createOrFindConsole(externalToolName);
} catch (PartInitException e) {
CodanUIActivator.log("Unable to create/find console", e); //$NON-NLS-1$
}
}
return ConsolePrinter.NullImpl;
return consolePrinterFactory.createConsolePrinter(externalToolName, shouldDisplayOutput);
}
private String buildCommand(IPath executablePath, String[] args) {
@ -87,7 +82,7 @@ public class CommandInvoker implements ICommandInvoker {
return runtime.exec(command, ENVIRONMENT_VARIABLE_SETTINGS, workingDirectory.toFile());
}
private void processStream(InputStream inputStream, List<IOutputParser> parsers,
private void processStream(InputStream inputStream, List<AbstractOutputParser> parsers,
ConsolePrinter consolePrinter) throws IOException, InvocationFailure {
Reader reader = null;
try {
@ -96,7 +91,7 @@ public class CommandInvoker implements ICommandInvoker {
String line = null;
while ((line = bufferedReader.readLine()) != null) {
consolePrinter.println(line);
for (IOutputParser parser : parsers) {
for (AbstractOutputParser parser : parsers) {
if (parser.parse(line)) {
break;
}
@ -110,4 +105,9 @@ public class CommandInvoker implements ICommandInvoker {
}
}
}
// Visible for testing.
void setConsolePrinterFactory(ConsolePrinterFactory newVal) {
this.consolePrinterFactory = newVal;
}
}

View file

@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* 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 - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.ui.externaltool;
import org.eclipse.cdt.codan.internal.ui.CodanUIActivator;
import org.eclipse.ui.PartInitException;
/**
* @author alruiz@google.com (Alex Ruiz)
*/
class ConsolePrinterFactory {
ConsolePrinter createConsolePrinter(String externalToolName, boolean shouldDisplayOutput) {
if (shouldDisplayOutput) {
try {
return ConsolePrinterImpl.createOrFindConsole(externalToolName);
} catch (PartInitException e) {
CodanUIActivator.log("Unable to create/find console", e); //$NON-NLS-1$
}
}
return ConsolePrinter.NullImpl;
}
}