package org.wangzw.plugin.cppstyle; import java.net.URI; import org.eclipse.cdt.codan.core.CodanRuntime; import org.eclipse.cdt.codan.core.cxx.externaltool.ArgsSeparator; import org.eclipse.cdt.codan.core.cxx.externaltool.InvocationFailure; 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.FileScopeProblemPreference; 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; import org.eclipse.core.runtime.Path; import org.wangzw.plugin.cppstyle.ui.CppStyleConstants; import org.wangzw.plugin.cppstyle.ui.CppStyleMessageConsole; public class CpplintChecker extends AbstractCheckerWithProblemPreferences implements IMarkerGenerator { private final ArgsSeparator argsSeparator; private final CpplintCheckSettings settings; private final CpplintInvoker invoker; private final RootProblemPreference preferences; /** * Constructor. */ public CpplintChecker() { this.argsSeparator = new ArgsSeparator(); this.settings = new CpplintCheckSettings(); this.invoker = new CpplintInvoker(); this.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) { if (!shouldProduceProblems(resource)) { return false; } if (!CpplintCheckSettings.checkCpplint(resource)) { return false; } process(resource); return false; } private void process(IResource resource) { try { CppStyleMessageConsole console = CppStyle.buildConsole(); console.getListener().setFile((IFile) resource); String path = resource.getLocation().toOSString(); InvocationParameters parameters = new InvocationParameters(resource, resource, path, null, console); 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 { invoker.invoke(parameters, settings, argsSeparator, parsers); } catch (InvocationFailure error) { handleInvocationFailure(error, parameters); } } private void updateConfigurationSettingsFromPreferences(IResource fileToProcess) { settings.updateValuesFrom((IFile) fileToProcess); } private ErrorParserManager createErrorParserManager(InvocationParameters parameters) { IProject project = parameters.getActualFile().getProject(); URI workingDirectory = URIUtil.toURI(parameters.getWorkingDirectory()); return new ErrorParserManager(project, workingDirectory, this, getParserIDs()); } /** * @return the IDs of the parsers to use to parse the output of the external * tool. */ protected String[] getParserIDs() { return new String[] { CppStyleConstants.CPPLINT_OUTPUT_PARSER_ID }; } /** * 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$ CppStyle.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 String getReferenceProblemId() { return CppStyleConstants.CPPLINT_ERROR_PROBLEM_ID; } @Override public void initPreferences(IProblemWorkingCopy problem) { getTopLevelPreference(problem); // initialize FileScopeProblemPreference scope = getScopePreference(problem); Path[] value = new Path[6]; value[0] = new Path("*.cc"); value[1] = new Path("*.h"); value[2] = new Path("*.cpp"); value[3] = new Path("*.cu"); value[4] = new Path("*.cuh"); value[5] = new Path("*.hpp"); scope.setAttribute(FileScopeProblemPreference.INCLUSION, value); getLaunchModePreference(problem).enableInLaunchModes(CheckerLaunchMode.RUN_ON_FILE_SAVE, CheckerLaunchMode.RUN_ON_DEMAND); } @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) { String problemId = info.getAttribute(CppStyleConstants.CPPLINT_PROBLEM_ID_KEY); reportProblem(problemId, 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); } }