summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Ruiz2012-02-23 15:25:05 (EST)
committerSergey Prigogin2012-02-23 15:25:05 (EST)
commit3115bb4e228e7d1903aaba91178d7ec9742c190e (patch)
tree9a4c4a8c743dc5769b8b1408a6f3656873d29593
parentac7ee03d2515bbfb234d5022db341dc07bd3627c (diff)
downloadorg.eclipse.cdt-3115bb4e228e7d1903aaba91178d7ec9742c190e.zip
org.eclipse.cdt-3115bb4e228e7d1903aaba91178d7ec9742c190e.tar.gz
org.eclipse.cdt-3115bb4e228e7d1903aaba91178d7ec9742c190e.tar.bz2
Initial take on external-tool-based checkers.
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/META-INF/MANIFEST.MF4
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/plugin.xml36
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckChecker.java73
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckOutputParser.java76
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckOutputParserFactory.java32
-rw-r--r--codan/org.eclipse.cdt.codan.core.cxx/META-INF/MANIFEST.MF3
-rw-r--r--codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/util/FileTypes.java68
-rw-r--r--codan/org.eclipse.cdt.codan.core/META-INF/MANIFEST.MF1
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ArgsSetting.java34
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ConfigurationSettings.java114
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IArgsSeparator.java31
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ICommandInvoker.java39
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IInvocationParametersProvider.java28
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IOutputParser.java34
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IOutputParserFactory.java29
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IProblemDisplay.java35
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ISupportedResourceVerifier.java38
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationFailure.java38
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParameters.java88
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParametersProvider.java38
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/Messages.java30
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/Messages.properties3
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/PathSetting.java35
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ShouldDisplayOutputSetting.java34
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SingleConfigurationSetting.java76
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SpaceDelimitedArgsSeparator.java33
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractExternalToolBasedChecker.java209
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java27
-rw-r--r--codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvoker.java102
-rw-r--r--codan/org.eclipse.cdt.codan.ui.cxx/META-INF/MANIFEST.MF3
-rw-r--r--codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/CEditors.java42
-rw-r--r--codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/CxxSupportedResourceVerifier.java59
-rw-r--r--codan/org.eclipse.cdt.codan.ui/META-INF/MANIFEST.MF4
-rw-r--r--codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIActivator.java14
-rw-r--r--codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/CodanEditorUtility.java5
-rw-r--r--codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/CommandInvoker.java113
-rw-r--r--codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinter.java54
-rw-r--r--codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterImpl.java81
38 files changed, 1756 insertions, 7 deletions
diff --git a/codan/org.eclipse.cdt.codan.checkers/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.checkers/META-INF/MANIFEST.MF
index 927ef13..016debe 100644
--- a/codan/org.eclipse.cdt.codan.checkers/META-INF/MANIFEST.MF
+++ b/codan/org.eclipse.cdt.codan.checkers/META-INF/MANIFEST.MF
@@ -8,7 +8,9 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.resources;bundle-version="3.5.0",
org.eclipse.cdt.codan.core;bundle-version="1.0.0",
org.eclipse.cdt.core;bundle-version="5.1.0",
- org.eclipse.cdt.codan.core.cxx;bundle-version="1.0.0"
+ org.eclipse.cdt.codan.core.cxx;bundle-version="1.0.0",
+ org.eclipse.cdt.codan.ui.cxx;bundle-version="3.0.0",
+ org.eclipse.cdt.codan.ui;bundle-version="2.0.1"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-Vendor: %Bundle-Vendor
diff --git a/codan/org.eclipse.cdt.codan.checkers/plugin.xml b/codan/org.eclipse.cdt.codan.checkers/plugin.xml
index 0f3f1c7..944b52a 100644
--- a/codan/org.eclipse.cdt.codan.checkers/plugin.xml
+++ b/codan/org.eclipse.cdt.codan.checkers/plugin.xml
@@ -398,5 +398,41 @@
name="%problem.name.ClassMembersInitialization">
</problem>
</checker>
+ <category
+ id="org.eclipse.cdt.codan.checkers.cppcheck"
+ name="Cppcheck Errors">
+ </category>
+ <checker
+ class="org.eclipse.cdt.codan.internal.checkers.CppcheckChecker"
+ id="org.eclipse.cdt.codan.checkers.CppcheckChecker"
+ name="Cppcheck">
+ <problem
+ category="org.eclipse.cdt.codan.checkers.cppcheck"
+ defaultEnabled="false"
+ defaultSeverity="Error"
+ description="Errors reported by Cppcheck (http://cppcheck.sourceforge.net/)"
+ id="org.eclipse.cdt.codan.checkers.cppcheck.error"
+ messagePattern="{0}"
+ name="Errors">
+ </problem>
+ <problem
+ category="org.eclipse.cdt.codan.checkers.cppcheck"
+ defaultEnabled="false"
+ defaultSeverity="Warning"
+ description="Warnings reported by Cppcheck (http://cppcheck.sourceforge.net/)"
+ id="org.eclipse.cdt.codan.checkers.cppcheck.warning"
+ messagePattern="{0}"
+ name="Warnings">
+ </problem>
+ <problem
+ category="org.eclipse.cdt.codan.checkers.cppcheck"
+ defaultEnabled="false"
+ defaultSeverity="Warning"
+ description="Style issues reported by Cppcheck (http://cppcheck.sourceforge.net/)"
+ id="org.eclipse.cdt.codan.checkers.cppcheck.style"
+ messagePattern="{0}"
+ name="Style Issues">
+ </problem>
+ </checker>
</extension>
</plugin>
diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckChecker.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckChecker.java
new file mode 100644
index 0000000..607b5cd
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckChecker.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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 java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+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.model.IProblemLocation;
+import org.eclipse.cdt.codan.ui.cxx.externaltool.CxxSupportedResourceVerifier;
+import org.eclipse.cdt.codan.ui.externaltool.CommandInvoker;
+
+/**
+ * Checker that invokes <a href="http://cppcheck.sourceforge.net/">Cppcheck</a> when a C/C++ is
+ * saved.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class CppcheckChecker extends AbstractExternalToolBasedChecker {
+ 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$
+
+ 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<String, String> PROBLEM_IDS = new HashMap<String, String>();
+ static {
+ ERROR_PROBLEM_ID = addProblemId("error"); //$NON-NLS-1$
+ addProblemId("warning"); //$NON-NLS-1$
+ addProblemId("style"); //$NON-NLS-1$
+ }
+ private static String addProblemId(String severity) {
+ String problemId = "org.eclipse.cdt.codan.checkers.cppcheck." + severity; //$NON-NLS-1$
+ PROBLEM_IDS.put(severity, problemId);
+ return problemId;
+ }
+
+ public CppcheckChecker() {
+ super(new InvocationParametersProvider(), new CxxSupportedResourceVerifier(),
+ new SpaceDelimitedArgsSeparator(), new CommandInvoker(),
+ new CppcheckOutputParserFactory(),
+ new ConfigurationSettings(TOOL_NAME, new File(EXECUTABLE_NAME), DEFAULT_ARGS));
+ }
+
+ @Override
+ public void reportProblem(IProblemLocation location, String description, String severity) {
+ String problemId = PROBLEM_IDS.get(severity);
+ if (problemId == null) {
+ problemId = getReferenceProblemId();
+ }
+ super.reportProblem(problemId, location, String.format(DESCRIPTION_FORMAT, description));
+ }
+
+ @Override
+ protected String getReferenceProblemId() {
+ return ERROR_PROBLEM_ID;
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckOutputParser.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckOutputParser.java
new file mode 100644
index 0000000..96a27e6
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckOutputParser.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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 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.IProblemDisplay;
+import org.eclipse.cdt.codan.core.externaltool.InvocationParameters;
+import org.eclipse.cdt.codan.core.model.IProblemLocation;
+import org.eclipse.cdt.codan.core.model.IProblemLocationFactory;
+import org.eclipse.core.resources.IFile;
+
+/**
+ * Parses the output of Cppcheck.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class CppcheckOutputParser implements IOutputParser {
+ // the pattern for parsing the message is:
+ //
+ // [/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$
+
+ private final InvocationParameters parameters;
+ private final IProblemDisplay problemDisplay;
+
+ CppcheckOutputParser(InvocationParameters parameters, IProblemDisplay problemDisplay) {
+ this.parameters = parameters;
+ this.problemDisplay = problemDisplay;
+ }
+
+ @Override
+ public boolean parse(String line) {
+ Matcher matcher = pattern.matcher(line);
+ if (!matcher.matches()) {
+ return false;
+ }
+ String filePath = matcher.group(1);
+ if (parameters.getActualFilePath().equals(filePath)) {
+ int lineNumber = Integer.parseInt(matcher.group(2));
+ String severity = matcher.group(3);
+ String description = matcher.group(4);
+ IProblemLocation location = createProblemLocation(lineNumber);
+ problemDisplay.reportProblem(location, description, severity);
+ }
+ return true;
+ }
+
+ private IProblemLocation createProblemLocation(int lineNumber) {
+ IProblemLocationFactory factory = CodanRuntime.getInstance().getProblemLocationFactory();
+ IFile actualFile = (IFile) parameters.getActualFile();
+ return factory.createProblemLocation(actualFile, -1, -1, lineNumber);
+ }
+
+ @Override
+ public void reset() {}
+}
diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckOutputParserFactory.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckOutputParserFactory.java
new file mode 100644
index 0000000..f29f58b
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CppcheckOutputParserFactory.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core.cxx/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.core.cxx/META-INF/MANIFEST.MF
index 5ae2687..e62db6b 100644
--- a/codan/org.eclipse.cdt.codan.core.cxx/META-INF/MANIFEST.MF
+++ b/codan/org.eclipse.cdt.codan.core.cxx/META-INF/MANIFEST.MF
@@ -12,6 +12,7 @@ Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.cdt.codan.core.cxx,
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.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,
+ org.eclipse.cdt.codan.core.cxx.util
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-Vendor: %Bundle-Vendor
diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/util/FileTypes.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/util/FileTypes.java
new file mode 100644
index 0000000..819a5c4
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/util/FileTypes.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * 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.cxx.util;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Utility methods related to C++ file types.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public final class FileTypes {
+ private static final String[] CPP_FILE_EXTENSIONS = {
+ "cc", //$NON-NLS-1$
+ "cpp", //$NON-NLS-1$
+ "cxx" //$NON-NLS-1$
+ };
+ private static final String[] HEADER_FILE_EXTENSIONS = { "h" }; //$NON-NLS-1$
+
+ /**
+ * Indicates whether the given <code>{@link IResource}</code> is a C++ file.
+ * @param resource the {@code IResource} to check.
+ * @return {@code true} if the given {@code IResource} is a C++ file; {@code false} otherwise.
+ */
+ public static boolean isCppFile(IResource resource) {
+ return isFileWithExtension(resource, CPP_FILE_EXTENSIONS);
+ }
+
+ /**
+ * Indicates whether the given <code>{@link IResource}</code> is a header file.
+ * @param resource the {@code IResource} to check.
+ * @return {@code true} if the given {@code IResource} is a header file; {@code false}
+ * otherwise.
+ */
+ public static boolean isHeaderFile(IResource resource) {
+ return isFileWithExtension(resource, HEADER_FILE_EXTENSIONS);
+ }
+
+ private static boolean isFileWithExtension(IResource resource, String[] validExtensions) {
+ if (!(resource instanceof IFile)) {
+ return false;
+ }
+ IPath path = resource.getFullPath();
+ return doesPathHaveExtension(path, validExtensions);
+ }
+
+ private static boolean doesPathHaveExtension(IPath path, String[] validExtensions) {
+ String fileExtension = path.getFileExtension();
+ for (String extension : validExtensions) {
+ if (extension.equalsIgnoreCase(fileExtension)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private FileTypes() {}
+}
diff --git a/codan/org.eclipse.cdt.codan.core/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.core/META-INF/MANIFEST.MF
index 674cf7b..3f2598e 100644
--- a/codan/org.eclipse.cdt.codan.core/META-INF/MANIFEST.MF
+++ b/codan/org.eclipse.cdt.codan.core/META-INF/MANIFEST.MF
@@ -10,6 +10,7 @@ Require-Bundle: org.eclipse.core.runtime,
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Export-Package: org.eclipse.cdt.codan.core,
+ org.eclipse.cdt.codan.core.externaltool,
org.eclipse.cdt.codan.core.model,
org.eclipse.cdt.codan.core.model.cfg;x-friends:="org.eclipse.cdt.codan.core.cxx,org.eclipse.cdt.codan.checkers",
org.eclipse.cdt.codan.core.param,
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ArgsSetting.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ArgsSetting.java
new file mode 100644
index 0000000..311b04b
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ArgsSetting.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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 static org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType.TYPE_STRING;
+
+import org.eclipse.cdt.codan.core.param.BasicProblemPreference;
+
+/**
+ * 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)
+ */
+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 defaultValue the default value of the setting.
+ */
+ public ArgsSetting(String label, String defaultValue) {
+ super(new BasicProblemPreference(KEY, label, TYPE_STRING), defaultValue, String.class);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ConfigurationSettings.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ConfigurationSettings.java
new file mode 100644
index 0000000..62cb816
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ConfigurationSettings.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * 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 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;
+
+/**
+ * User-configurable external tool settings.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ConfigurationSettings {
+ private final PathSetting path;
+ private final ArgsSetting args;
+ private final ShouldDisplayOutputSetting shouldDisplayOutput;
+ private final String externalToolName;
+
+ /**
+ * 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
+ * displayed in an Eclipse console.
+ */
+ public ConfigurationSettings(String externalToolName, PathSetting path, ArgsSetting args,
+ ShouldDisplayOutputSetting shouldDisplayOutput) {
+ this.externalToolName = externalToolName;
+ this.path = path;
+ this.args = args;
+ this.shouldDisplayOutput = shouldDisplayOutput;
+ }
+
+ /**
+ * 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 PathSetting 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 ArgsSetting getArgs() {
+ return args;
+ }
+
+ /**
+ * Returns the setting that specifies whether the output of the external tools should be
+ * displayed in an Eclipse console.
+ * @return the shouldDisplayOutput the setting that specifies whether the output of the external
+ * tools should be displayed in an Eclipse console.
+ */
+ public ShouldDisplayOutputSetting getShouldDisplayOutput() {
+ return shouldDisplayOutput;
+ }
+
+ /**
+ * 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);
+ shouldDisplayOutput.updateValue(preferences);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IArgsSeparator.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IArgsSeparator.java
new file mode 100644
index 0000000..5c687a1
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IArgsSeparator.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * Parses and separates the value of an <code>{@link ArgsSetting}</code> into an array of
+ * {@code String}s.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+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.
+ * @return the separated argument values.
+ */
+ String[] separateArgs(String args);
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ICommandInvoker.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ICommandInvoker.java
new file mode 100644
index 0000000..37e9836
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ICommandInvoker.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ *
+ */
+public interface ICommandInvoker {
+ /**
+ * Builds and launches the command necessary to invoke an external tool.
+ * @param project the current project.
+ * @param externalToolName the name of the external tool.
+ * @param executablePath the path and name of the external tool executable.
+ * @param args the arguments to pass to the external tool executable.
+ * @param workingDirectory the directory where the external tool should be executed.
+ * @param shouldDisplayOutput indicates whether the output of the external tools should be
+ * displayed in an Eclipse console.
+ * @param parsers parse the output of the external tool.
+ * @throws InvocationFailure if the external tool reports that it cannot be executed.
+ * @throws Throwable if the external tool cannot be launched.
+ */
+ void buildAndLaunchCommand(IProject project, String externalToolName, IPath executablePath,
+ String[] args, IPath workingDirectory, boolean shouldDisplayOutput,
+ List<IOutputParser> parsers) throws InvocationFailure, Throwable;
+} \ No newline at end of file
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IInvocationParametersProvider.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IInvocationParametersProvider.java
new file mode 100644
index 0000000..b2d6bb2
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IInvocationParametersProvider.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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 org.eclipse.core.resources.IResource;
+
+/**
+ * Provides the parameters to pass when invoking an external tool.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+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;
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IOutputParser.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IOutputParser.java
new file mode 100644
index 0000000..ddd460c
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IOutputParser.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * Parses the output of an external tool.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public interface IOutputParser {
+ /**
+ * Parses one line of output. Implementations are free to create markers from the information
+ * retrieved from the parsed output.
+ * @param line the line to parse.
+ * @return {@code true} if the line was successfully parsed; {@code false} otherwise.
+ * @throws InvocationFailure if the output indicates that the invocation of the external tool
+ * failed.
+ */
+ boolean parse(String line) throws InvocationFailure;
+
+ /**
+ * Resets the value of this parser, usually after the execution of the external tool is
+ * finished.
+ */
+ void reset();
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IOutputParserFactory.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IOutputParserFactory.java
new file mode 100644
index 0000000..008bb5b
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IOutputParserFactory.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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);
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IProblemDisplay.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IProblemDisplay.java
new file mode 100644
index 0000000..a4a054d
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IProblemDisplay.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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 org.eclipse.cdt.codan.core.model.IProblemLocation;
+
+/**
+ * Reports problems found in code, reported by an external tool.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public interface IProblemDisplay {
+ /**
+ * Reports a problem found by an external tool.
+ * @param location the problem's location (e.g. file and line number.)
+ * @param description the description of the problem.
+ */
+ void reportProblem(IProblemLocation location, String description);
+
+ /**
+ * Reports a problem found by an external tool.
+ * @param location the problem's location (e.g. file and line number.)
+ * @param description the description of the problem.
+ * @param severity the problem's severity (e.g. "error", "warning", etc.)
+ */
+ void reportProblem(IProblemLocation location, String description, String severity);
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ISupportedResourceVerifier.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ISupportedResourceVerifier.java
new file mode 100644
index 0000000..210ac8d
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ISupportedResourceVerifier.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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 org.eclipse.core.resources.IFile;
+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)
+ */
+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:
+ * <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.
+ */
+ boolean isSupported(IResource resource);
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationFailure.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationFailure.java
new file mode 100644
index 0000000..4e9236b
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationFailure.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * Indicates that invocation of an external tool failed.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class InvocationFailure extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 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);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParameters.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParameters.java
new file mode 100644
index 0000000..118886e
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParameters.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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 org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Parameters to pass when invoking an external tool.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public 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 #getActualFile()}</code>, depending on how the external tool works.
+ * <p>
+ * A good example is an external tool that can only process C++ files but 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;
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParametersProvider.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParametersProvider.java
new file mode 100644
index 0000000..b5fc686
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParametersProvider.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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 org.eclipse.core.resources.IResource;
+
+/**
+ * Default implementation of <code>{@link InvocationParameters}</code>
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+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);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/Messages.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/Messages.java
new file mode 100644
index 0000000..c3f3913
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/Messages.java
@@ -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.core.externaltool;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@SuppressWarnings("javadoc")
+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 {
+ Class<Messages> clazz = Messages.class;
+ NLS.initializeMessages(clazz.getName(), clazz);
+ }
+
+ private Messages() {}
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/Messages.properties b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/Messages.properties
new file mode 100644
index 0000000..fefe189
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/Messages.properties
@@ -0,0 +1,3 @@
+ConfigurationSettings_args_format=%s Args:
+ConfigurationSettings_path_format=%s Path:
+ConfigurationSettings_should_display_output=Display Output in Console
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/PathSetting.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/PathSetting.java
new file mode 100644
index 0000000..fb11bd6
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/PathSetting.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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 static org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType.TYPE_FILE;
+
+import java.io.File;
+
+import org.eclipse.cdt.codan.core.param.BasicProblemPreference;
+
+/**
+ * User-configurable setting that specifies the path and name of an external tool's executable.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+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 defaultValue the default value of the setting.
+ */
+ public PathSetting(String label, File defaultValue) {
+ super(new BasicProblemPreference(KEY, label, TYPE_FILE), defaultValue, File.class);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ShouldDisplayOutputSetting.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ShouldDisplayOutputSetting.java
new file mode 100644
index 0000000..6ffb934
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ShouldDisplayOutputSetting.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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 static org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType.TYPE_BOOLEAN;
+
+import org.eclipse.cdt.codan.core.param.BasicProblemPreference;
+
+/**
+ * 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)
+ */
+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);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SingleConfigurationSetting.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SingleConfigurationSetting.java
new file mode 100644
index 0000000..6c795b4
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SingleConfigurationSetting.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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 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.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+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) {
+ Object o = preferences.getChildValue(descriptor.getKey());
+ value = valueType.cast(o);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SpaceDelimitedArgsSeparator.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SpaceDelimitedArgsSeparator.java
new file mode 100644
index 0000000..0a79dbc
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SpaceDelimitedArgsSeparator.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.regex.Pattern;
+
+/**
+ * Separates the value of an <code>{@link ArgsSetting}</code> using an empty space as delimiter.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class SpaceDelimitedArgsSeparator implements IArgsSeparator {
+ private static final Pattern EMPTY_SPACE_PATTERN = Pattern.compile("\\s+"); //$NON-NLS-1$
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String[] separateArgs(String args) {
+ if (args == null || args.isEmpty()) {
+ return NO_ARGS;
+ }
+ return EMPTY_SPACE_PATTERN.split(args);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractExternalToolBasedChecker.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractExternalToolBasedChecker.java
new file mode 100644
index 0000000..928465e
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractExternalToolBasedChecker.java
@@ -0,0 +1,209 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+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.ConfigurationSettings;
+import org.eclipse.cdt.codan.core.externaltool.IArgsSeparator;
+import org.eclipse.cdt.codan.core.externaltool.ICommandInvoker;
+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;
+import org.eclipse.cdt.codan.core.externaltool.InvocationParameters;
+import org.eclipse.cdt.codan.core.externaltool.SingleConfigurationSetting;
+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.codan.internal.core.externaltool.ExternalToolInvoker;
+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 enable to run while the user types, since
+ * external tools cannot see unsaved changes.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWithProblemPreferences
+ implements IProblemDisplay {
+ private static final boolean DO_NOT_TRAVERSE_CHILDREN = false;
+
+ 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;
+
+ /**
+ * 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 commandInvoker builds and launches the command necessary to invoke the external tool.
+ * @param outputParserFactory creates parsers for the output of 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) {
+ this.parametersProvider = parametersProvider;
+ this.supportedResourceVerifier = supportedResourceVerifier;
+ this.argsSeparator = argsSeparator;
+ this.outputParserFactory = outputParserFactory;
+ this.configurationSettings = configurationSettings;
+ externalToolInvoker = new ExternalToolInvoker(commandInvoker);
+ preferences = new SharedRootProblemPreference();
+ }
+
+ /**
+ * Indicates whether this checker can process the given resource. For more details, please
+ * see <code>{@link ISupportedResourceVerifier#isSupported(IResource)}</code>.
+ * @param resource the given resource.
+ * @return {@code true} if this checker can process the given resource, {@code false} otherwise.
+ */
+ @Override
+ public boolean enabledInContext(IResource resource) {
+ return supportedResourceVerifier.isSupported(resource);
+ }
+
+ /**
+ * Indicates whether this checker is enabled to run while the user types. By default, this
+ * method returns {@code false}.
+ * <p>
+ * Running command-line based checkers while the user types is unnecessary and wasteful, since
+ * command-line tools are expensive to call (they run in a separate process) and they cannot
+ * see unsaved changes.
+ * </p>
+ * @return {@code false}.
+ */
+ @Override
+ public boolean runInEditor() {
+ return false;
+ }
+
+ @Override
+ public boolean processResource(IResource resource) {
+ process(resource);
+ return DO_NOT_TRAVERSE_CHILDREN;
+ }
+
+ 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());
+ List<IOutputParser> parsers = outputParserFactory.createParsers(parameters, this);
+ try {
+ externalToolInvoker.invoke(parameters, configurationSettings, argsSeparator, parsers);
+ } catch (InvocationFailure error) {
+ handleInvocationFailure(error, parameters);
+ }
+ }
+
+ private void updateConfigurationSettingsFromPreferences(IResource fileToProcess) {
+ IProblem problem = getProblemById(getReferenceProblemId(), fileToProcess);
+ MapProblemPreference preferences = (MapProblemPreference) problem.getPreference();
+ configurationSettings.updateValuesFrom(preferences);
+ }
+
+ /**
+ * 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$
+ CodanCorePlugin.log(msg, error);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void reportProblem(IProblemLocation location, String description) {
+ String severity = null;
+ reportProblem(location, description, severity);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void reportProblem(IProblemLocation location, String description, String severity) {
+ super.reportProblem(getReferenceProblemId(), location, description);
+ }
+
+ /**
+ * 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();
+
+ /**
+ * Initializes the preferences of the given problem. All preferences in a external-tool-based
+ * checker are shared among its defined problems.
+ * @param problem the given problem.
+ */
+ @Override
+ public void initPreferences(IProblemWorkingCopy problem) {
+ super.initPreferences(problem);
+ addPreference(problem, configurationSettings.getPath());
+ addPreference(problem, configurationSettings.getArgs());
+ addPreference(problem, configurationSettings.getShouldDisplayOutput());
+ }
+
+ private void addPreference(IProblemWorkingCopy problem, SingleConfigurationSetting<?> setting) {
+ IProblemPreference descriptor = (IProblemPreference) setting.getDescriptor();
+ addPreference(problem, descriptor, setting.getDefaultValue());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void setDefaultPreferenceValue(IProblemWorkingCopy problem, String key,
+ Object defaultValue) {
+ MapProblemPreference map = getTopLevelPreference(problem);
+ map.setChildValue(key, defaultValue);
+ }
+
+ /** {@inheritDoc} */
+ @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;
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java
new file mode 100644
index 0000000..dea9e27
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/param/SharedRootProblemPreference.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.param;
+
+
+/**
+ * Preferences that can be shared among several problems.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+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;
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvoker.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvoker.java
new file mode 100644
index 0000000..e5aa17f
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvoker.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * 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 java.io.File;
+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.InvocationFailure;
+import org.eclipse.cdt.codan.core.externaltool.InvocationParameters;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+/**
+ * Invokes an external tool to perform checks on a single file.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ExternalToolInvoker {
+ private final ICommandInvoker commandInvoker;
+
+ /**
+ * Constructor.
+ * @param commandInvoker builds and launches the command necessary to invoke the external tool.
+ */
+ public ExternalToolInvoker(ICommandInvoker commandInvoker) {
+ this.commandInvoker = commandInvoker;
+ }
+
+ /**
+ * 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 parsers parse the output of the external tool.
+ * @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 {
+ 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,
+ parameters.getWorkingDirectory(), shouldDisplayOutput, parsers);
+ } finally {
+ reset(parsers);
+ }
+ }
+
+ private IPath executablePath(ConfigurationSettings configurationSettings) {
+ File executablePath = configurationSettings.getPath().getValue();
+ return new Path(executablePath.toString());
+ }
+
+ 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) {
+ String args = configurationSettings.getArgs().getValue();
+ return argsSeparator.separateArgs(args);
+ }
+
+ private String[] addFilePathToArgs(String actualFilePath, String[] configuredArgs) {
+ int argCount = configuredArgs.length;
+ String[] allArgs = new String[argCount + 1];
+ // add file to process as the first argument
+ allArgs[0] = actualFilePath;
+ for (int i = 0; i < argCount; i++) {
+ allArgs[i + 1] = configuredArgs[i];
+ }
+ return allArgs;
+ }
+
+ private void reset(List<IOutputParser> parsers) {
+ for (IOutputParser parser : parsers) {
+ parser.reset();
+ }
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.ui.cxx/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.ui.cxx/META-INF/MANIFEST.MF
index abedd16..80bc1e7 100644
--- a/codan/org.eclipse.cdt.codan.ui.cxx/META-INF/MANIFEST.MF
+++ b/codan/org.eclipse.cdt.codan.ui.cxx/META-INF/MANIFEST.MF
@@ -19,4 +19,5 @@ Require-Bundle: org.eclipse.ui,
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.cdt.codan.internal.ui.cxx;x-internal:=true,
- org.eclipse.cdt.codan.ui
+ org.eclipse.cdt.codan.ui,
+ org.eclipse.cdt.codan.ui.cxx.externaltool
diff --git a/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/CEditors.java b/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/CEditors.java
new file mode 100644
index 0000000..b9b3c9e
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/CEditors.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.internal.ui.editor.CEditor;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.editors.text.TextEditor;
+
+/**
+ * Utility methods related to <code>{@link CEditor}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@SuppressWarnings("restriction") // CEditor is internal API
+final class CEditors {
+
+ static TextEditor activeCEditor() {
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ for (IWorkbenchWindow w : workbench.getWorkbenchWindows()) {
+ IWorkbenchPage activePage = w.getActivePage();
+ IEditorPart editor = activePage.getActiveEditor();
+ if (editor instanceof CEditor) {
+ return (CEditor) editor;
+ }
+ }
+ return null;
+ }
+
+ private CEditors() {}
+}
diff --git a/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/CxxSupportedResourceVerifier.java b/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/CxxSupportedResourceVerifier.java
new file mode 100644
index 0000000..4667d3b
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/CxxSupportedResourceVerifier.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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 static org.eclipse.cdt.codan.core.cxx.util.FileTypes.isCppFile;
+import static org.eclipse.cdt.codan.core.cxx.util.FileTypes.isHeaderFile;
+import static org.eclipse.cdt.codan.ui.CodanEditorUtility.isResourceOpenInEditor;
+import static org.eclipse.cdt.codan.ui.cxx.externaltool.CEditors.activeCEditor;
+
+import org.eclipse.cdt.codan.core.externaltool.ISupportedResourceVerifier;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.ui.editors.text.TextEditor;
+
+/**
+ * Implemenation of <code>{@link ISupportedResourceVerifier}</code> for C/C++ files.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class CxxSupportedResourceVerifier implements 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:
+ * <ul>
+ * <li>should be C/C++ file</li>
+ * <li>should be displayed in the current active {@code CEditor}</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.
+ */
+ @Override
+ public boolean isSupported(IResource resource) {
+ return isFileOfSupportedType(resource) && isOpenInActiveCEditor(resource);
+ }
+
+ private boolean isFileOfSupportedType(IResource resource) {
+ return isCppFile(resource) || isHeaderFile(resource);
+ }
+
+ private boolean isOpenInActiveCEditor(IResource resource) {
+ TextEditor activeCEditor = activeCEditor();
+ if (activeCEditor == null) {
+ return false;
+ }
+ return !activeCEditor.isDirty() && isResourceOpenInEditor(resource, activeCEditor);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.ui/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.ui/META-INF/MANIFEST.MF
index af09ae6..f915a5f 100644
--- a/codan/org.eclipse.cdt.codan.ui/META-INF/MANIFEST.MF
+++ b/codan/org.eclipse.cdt.codan.ui/META-INF/MANIFEST.MF
@@ -13,7 +13,8 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.jface.text,
org.eclipse.ui.ide,
org.eclipse.cdt.ui,
- org.eclipse.core.filesystem
+ org.eclipse.core.filesystem,
+ org.eclipse.ui.console;bundle-version="3.5.100"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.cdt.codan.internal.ui;x-friends:="org.eclipse.cdt.codan.ui.cxx",
@@ -23,5 +24,6 @@ Export-Package: org.eclipse.cdt.codan.internal.ui;x-friends:="org.eclipse.cdt.co
org.eclipse.cdt.codan.internal.ui.views;x-internal:=true,
org.eclipse.cdt.codan.internal.ui.widgets;x-internal:=true,
org.eclipse.cdt.codan.ui,
+ org.eclipse.cdt.codan.ui.externaltool,
org.eclipse.cdt.codan.ui.handlers
diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIActivator.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIActivator.java
index fcd4c90..20800ee 100644
--- a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIActivator.java
+++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/internal/ui/CodanUIActivator.java
@@ -83,7 +83,7 @@ public class CodanUIActivator extends AbstractUIPlugin {
}
/**
- * Logs an internal error with the specified throwable
+ * Logs an internal error with the specified {@code Throwable}.
*
* @param e
* the exception to be logged
@@ -103,6 +103,18 @@ public class CodanUIActivator extends AbstractUIPlugin {
}
/**
+ * Logs an internal error with the specified message and {@code Throwable}.
+ *
+ * @param message
+ * the error message to log
+ * @param e
+ * the exception to be logged
+ */
+ public static void log(String message, Throwable e) {
+ log(new Status(IStatus.ERROR, PLUGIN_ID, 1, message, e));
+ }
+
+ /**
* @return
*/
public IPreferenceStore getCorePreferenceStore() {
diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/CodanEditorUtility.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/CodanEditorUtility.java
index 8c5c40e..7cb3830 100644
--- a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/CodanEditorUtility.java
+++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/CodanEditorUtility.java
@@ -158,9 +158,10 @@ public class CodanEditorUtility {
}
/**
- * @return
+ * Returns the active workbench page.
+ * @return the active workbench page, or {@code null} if none can be found.
*/
- private static IWorkbenchPage getActivePage() {
+ public static IWorkbenchPage getActivePage() {
IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (activeWorkbenchWindow == null)
return null;
diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/CommandInvoker.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/CommandInvoker.java
new file mode 100644
index 0000000..5140080
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/CommandInvoker.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * 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 java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+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.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)
+ */
+public class CommandInvoker implements ICommandInvoker {
+ private static final String[] ENVIRONMENT_VARIABLE_SETTINGS = {};
+
+ @Override
+ public void buildAndLaunchCommand(IProject project, String externalToolName,
+ IPath executablePath, String[] args, IPath workingDirectory, boolean shouldDisplayOutput,
+ List<IOutputParser> parsers) throws InvocationFailure, Throwable {
+ ConsolePrinter consolePrinter = consolePrinter(externalToolName, shouldDisplayOutput);
+ String command = buildCommand(executablePath, args);
+ Process process = null;
+ try {
+ consolePrinter.clear();
+ consolePrinter.println(command);
+ consolePrinter.println();
+ try {
+ process = invoke(command, workingDirectory);
+ } catch (IOException e) {
+ throw new InvocationFailure("Unable to start " + externalToolName, e); //$NON-NLS-1$
+ }
+ processStream(process.getInputStream(), parsers, consolePrinter);
+ processStream(process.getErrorStream(), parsers, consolePrinter);
+ } finally {
+ if (process != null) {
+ process.destroy();
+ }
+ consolePrinter.close();
+ }
+ }
+
+ 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;
+ }
+
+ private String buildCommand(IPath executablePath, String[] args) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(executablePath.toOSString());
+ for (String arg : args) {
+ builder.append(" ").append(arg); //$NON-NLS-1$
+ }
+ return builder.toString();
+ }
+
+ private Process invoke(String command, IPath workingDirectory) throws IOException {
+ Runtime runtime = Runtime.getRuntime();
+ if (workingDirectory == null) {
+ return runtime.exec(command);
+ }
+ return runtime.exec(command, ENVIRONMENT_VARIABLE_SETTINGS, workingDirectory.toFile());
+ }
+
+ private void processStream(InputStream inputStream, List<IOutputParser> parsers,
+ ConsolePrinter consolePrinter) throws IOException, InvocationFailure {
+ Reader reader = null;
+ try {
+ reader = new InputStreamReader(inputStream);
+ BufferedReader bufferedReader = new BufferedReader(reader);
+ String line = null;
+ while ((line = bufferedReader.readLine()) != null) {
+ consolePrinter.println(line);
+ for (IOutputParser parser : parsers) {
+ if (parser.parse(line)) {
+ break;
+ }
+ }
+ }
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException ignored) {}
+ }
+ }
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinter.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinter.java
new file mode 100644
index 0000000..41ac713
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinter.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * Prints the output of an external tool to an Eclipse console. It uses the name of the external
+ * tool as the console ID.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+interface ConsolePrinter {
+ ConsolePrinter NullImpl = new ConsolePrinter() {
+ @Override
+ public void clear() {}
+
+ @Override
+ public void println(String message) {}
+
+ @Override
+ public void println() {}
+
+ @Override
+ public void close() {}
+ };
+
+ /**
+ * Clears the contents of the console.
+ */
+ void clear();
+
+ /**
+ * Prints the specified message to the console, followed by a line separator string.
+ * @param message the message to print.
+ */
+ void println(String message);
+
+ /**
+ * Prints a line separator to the console.
+ */
+ void println();
+
+ /**
+ * Closes the output stream of the console.
+ */
+ void close();
+}
diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterImpl.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterImpl.java
new file mode 100644
index 0000000..abaf246
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterImpl.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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 static org.eclipse.ui.console.IConsoleConstants.ID_CONSOLE_VIEW;
+
+import java.io.IOException;
+
+import org.eclipse.cdt.codan.ui.CodanEditorUtility;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.console.ConsolePlugin;
+import org.eclipse.ui.console.IConsole;
+import org.eclipse.ui.console.IConsoleManager;
+import org.eclipse.ui.console.IConsoleView;
+import org.eclipse.ui.console.MessageConsole;
+import org.eclipse.ui.console.MessageConsoleStream;
+
+/**
+ * Default implementation of <code>{@link ConsolePrinter}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class ConsolePrinterImpl implements ConsolePrinter {
+ private final MessageConsole console;
+ private final MessageConsoleStream out;
+
+ static ConsolePrinter createOrFindConsole(String externalToolName)
+ throws PartInitException {
+ MessageConsole console = findConsole(externalToolName);
+ IWorkbenchPage page = CodanEditorUtility.getActivePage();
+ if (page != null) {
+ IConsoleView view = (IConsoleView) page.showView(ID_CONSOLE_VIEW);
+ view.display(console);
+ }
+ return new ConsolePrinterImpl(console);
+ }
+
+ private static MessageConsole findConsole(String externalToolName) {
+ IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();
+ for (IConsole console : consoleManager.getConsoles()) {
+ if (externalToolName.equals(console.getName()) && console instanceof MessageConsole) {
+ return (MessageConsole) console;
+ }
+ }
+ MessageConsole console = new MessageConsole(externalToolName, null);
+ consoleManager.addConsoles(new IConsole[] { console });
+ return console;
+ }
+
+ private ConsolePrinterImpl(MessageConsole console) {
+ this.console = console;
+ out = console.newMessageStream();
+ }
+
+ public void clear() {
+ console.clearConsole();
+ }
+
+ public void println(String s) {
+ out.println(s);
+ }
+
+ public void println() {
+ out.println();
+ }
+
+ public void close() {
+ try {
+ out.close();
+ } catch (IOException ignored) {}
+ }
+}