Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java')
-rw-r--r--codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java214
1 files changed, 214 insertions, 0 deletions
diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java
new file mode 100644
index 00000000000..6797af3a3ca
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/externaltool/AbstractExternalToolBasedChecker.java
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Google, Inc and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alex Ruiz (Google) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.cxx.externaltool;
+
+import static org.eclipse.cdt.core.ErrorParserContext.CODAN;
+
+import java.net.URI;
+
+import org.eclipse.cdt.codan.core.CodanRuntime;
+import org.eclipse.cdt.codan.core.cxx.Activator;
+import org.eclipse.cdt.codan.core.cxx.internal.externaltool.ExternalToolInvoker;
+import org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences;
+import org.eclipse.cdt.codan.core.model.CheckerLaunchMode;
+import org.eclipse.cdt.codan.core.model.IProblem;
+import org.eclipse.cdt.codan.core.model.IProblemLocation;
+import org.eclipse.cdt.codan.core.model.IProblemLocationFactory;
+import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
+import org.eclipse.cdt.codan.core.param.IProblemPreference;
+import org.eclipse.cdt.codan.core.param.MapProblemPreference;
+import org.eclipse.cdt.codan.core.param.RootProblemPreference;
+import org.eclipse.cdt.codan.core.param.SharedRootProblemPreference;
+import org.eclipse.cdt.core.ErrorParserManager;
+import org.eclipse.cdt.core.IConsoleParser;
+import org.eclipse.cdt.core.IMarkerGenerator;
+import org.eclipse.cdt.core.ProblemMarkerInfo;
+import org.eclipse.core.filesystem.URIUtil;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+
+/**
+ * Base class for checkers that invoke external command-line tools to perform code checking.
+ * <p>
+ * A file, to be processed by this type of checker, must:
+ * <ol>
+ * <li>be in the current active editor</li>
+ * <li>not have any unsaved changes</li>
+ * </ol>
+ * </p>
+ * By default, implementations of this checker are not allowed to run while the user types, since
+ * external tools cannot see unsaved changes.
+ *
+ * @since 2.1
+ */
+public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWithProblemPreferences
+ implements IMarkerGenerator {
+ private final IInvocationParametersProvider parametersProvider;
+ private final ArgsSeparator argsSeparator;
+ private final ConfigurationSettings settings;
+ private final ExternalToolInvoker externalToolInvoker;
+ private final RootProblemPreference preferences;
+
+ /**
+ * Constructor.
+ * @param settings user-configurable external tool configuration settings.
+ */
+ public AbstractExternalToolBasedChecker(ConfigurationSettings settings) {
+ this(new InvocationParametersProvider(), new ArgsSeparator(), settings);
+ }
+
+ /**
+ * Constructor.
+ * @param parametersProvider provides the parameters to pass when invoking the external tool.
+ * @param argsSeparator separates the arguments to pass to the external tool executable. These
+ * arguments are stored in a single {@code String}.
+ * @param settings user-configurable external tool configuration settings.
+ */
+ public AbstractExternalToolBasedChecker(IInvocationParametersProvider parametersProvider,
+ ArgsSeparator argsSeparator, ConfigurationSettings settings) {
+ this.parametersProvider = parametersProvider;
+ this.argsSeparator = argsSeparator;
+ this.settings = settings;
+ externalToolInvoker = new ExternalToolInvoker();
+ preferences = new SharedRootProblemPreference();
+ }
+
+ /**
+ * Returns {@code false} because this checker cannot run "as you type" by default.
+ * @return {@code false}.
+ */
+ @Override
+ public boolean runInEditor() {
+ return false;
+ }
+
+ @Override
+ public boolean processResource(IResource resource) {
+ process(resource);
+ return false;
+ }
+
+ private void process(IResource resource) {
+ try {
+ InvocationParameters parameters = parametersProvider.createParameters(resource);
+ if (parameters != null) {
+ invokeExternalTool(parameters);
+ }
+ } catch (Throwable error) {
+ logResourceProcessingFailure(error, resource);
+ }
+ }
+
+ private void invokeExternalTool(InvocationParameters parameters) throws Throwable {
+ updateConfigurationSettingsFromPreferences(parameters.getActualFile());
+ IConsoleParser[] parsers = new IConsoleParser[] { createErrorParserManager(parameters) };
+ try {
+ externalToolInvoker.invoke(parameters, settings, argsSeparator, parsers);
+ } catch (InvocationFailure error) {
+ handleInvocationFailure(error, parameters);
+ }
+ }
+
+ private void updateConfigurationSettingsFromPreferences(IResource fileToProcess) {
+ IProblem problem = getProblemById(getReferenceProblemId(), fileToProcess);
+ MapProblemPreference preferences = (MapProblemPreference) problem.getPreference();
+ settings.updateValuesFrom(preferences);
+ }
+
+ private ErrorParserManager createErrorParserManager(InvocationParameters parameters) {
+ IProject project = parameters.getActualFile().getProject();
+ URI workingDirectory = URIUtil.toURI(parameters.getWorkingDirectory());
+ return new ErrorParserManager(project, workingDirectory, this, getParserIDs(), CODAN);
+ }
+
+ /**
+ * @return the IDs of the parsers to use to parse the output of the external tool.
+ */
+ protected abstract String[] getParserIDs();
+
+ /**
+ * Handles a failure reported when invoking the external tool. This implementation simply
+ * logs the failure.
+ * @param error the reported failure.
+ * @param parameters the parameters passed to the external tool executable.
+ */
+ protected void handleInvocationFailure(InvocationFailure error, InvocationParameters parameters) {
+ logResourceProcessingFailure(error, parameters.getActualFile());
+ }
+
+ private void logResourceProcessingFailure(Throwable error, IResource resource) {
+ String location = resource.getLocation().toOSString();
+ String msg = String.format("Unable to process resource %s", location); //$NON-NLS-1$
+ Activator.log(msg, error);
+ }
+
+ /**
+ * Returns the id of the problem used as reference to obtain this checker's preferences. All
+ * preferences in a external-tool-based checker are shared among its defined problems.
+ * @return the id of the problem used as reference to obtain this checker's preferences.
+ */
+ protected abstract String getReferenceProblemId();
+
+ @Override
+ public void initPreferences(IProblemWorkingCopy problem) {
+ super.initPreferences(problem);
+ getLaunchModePreference(problem).enableInLaunchModes(
+ CheckerLaunchMode.RUN_ON_FULL_BUILD,
+ CheckerLaunchMode.RUN_ON_INC_BUILD,
+ CheckerLaunchMode.RUN_ON_FILE_SAVE,
+ CheckerLaunchMode.RUN_ON_DEMAND);
+ addPreference(problem, settings.getPath());
+ addPreference(problem, settings.getArgs());
+ }
+
+ private void addPreference(IProblemWorkingCopy problem, SingleConfigurationSetting<?> setting) {
+ IProblemPreference descriptor = (IProblemPreference) setting.getDescriptor();
+ addPreference(problem, descriptor, setting.getDefaultValue());
+ }
+
+ @Override
+ protected void setDefaultPreferenceValue(IProblemWorkingCopy problem, String key,
+ Object defaultValue) {
+ MapProblemPreference map = getTopLevelPreference(problem);
+ map.setChildValue(key, defaultValue);
+ }
+
+ @Override
+ public RootProblemPreference getTopLevelPreference(IProblem problem) {
+ RootProblemPreference map = (RootProblemPreference) problem.getPreference();
+ if (map == null) {
+ map = preferences;
+ if (problem instanceof IProblemWorkingCopy) {
+ ((IProblemWorkingCopy) problem).setPreference(map);
+ }
+ }
+ return map;
+ }
+
+ @Deprecated
+ @Override
+ public void addMarker(IResource file, int lineNumber, String description, int severity,
+ String variableName) {
+ addMarker(new ProblemMarkerInfo(file, lineNumber, description, severity, variableName));
+ }
+
+ @Override
+ public void addMarker(ProblemMarkerInfo info) {
+ reportProblem(getReferenceProblemId(), createProblemLocation(info), info.description);
+ }
+
+ protected IProblemLocation createProblemLocation(ProblemMarkerInfo info) {
+ IProblemLocationFactory factory = CodanRuntime.getInstance().getProblemLocationFactory();
+ return factory.createProblemLocation(
+ (IFile) info.file, info.startChar, info.endChar, info.lineNumber);
+ }
+}

Back to the top