/******************************************************************************* * Copyright (c) 2009, 2016 Alena Laskavaia * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Alena Laskavaia - initial API and implementation * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.codan.core.model; import java.util.ArrayList; import java.util.List; import org.eclipse.cdt.codan.core.CodanRuntime; import org.eclipse.cdt.codan.internal.core.CheckersRegistry; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.OperationCanceledException; /** * Convenience implementation of IChecker interface. Has a default * implementation for common methods. */ public abstract class AbstractChecker implements IChecker { private static final Object[] EMPTY_OBJECT_ARRAY = {}; private ICheckerInvocationContext context; private IProblemReporter problemReporter; /** * Default constructor */ public AbstractChecker() { } /** * Reports a simple problem for given file and line * * @param id * - problem id * @param file * - file * @param lineNumber * - line * @param args * - problem arguments, if problem does not define error message * it will be error message (not recommended because of * internationalization) */ public void reportProblem(String id, IFile file, int lineNumber, Object... args) { reportProblem(id, createProblemLocation(file, lineNumber), args); } /** * Finds an instance of problem by given id, in user profile registered for * specific file * * @param id * - problem id * @param file * - file in scope * @return problem instance */ public IProblem getProblemById(String id, IResource file) { IProblem problem = CheckersRegistry.getInstance().getResourceProfile(file).findProblem(id); if (problem == null) throw new IllegalArgumentException("Id is not registered"); //$NON-NLS-1$ return problem; } /** * @param id - main problem id * @param file - checked resource * @return - list of problems matching with this id, including duplicates * @since 2.0 */ public List<IProblem> getProblemsByMainId(String id, IResource file) { ArrayList<IProblem> list = new ArrayList<IProblem>(); IProblemProfile resourceProfile = CheckersRegistry.getInstance().getResourceProfile(file); IProblem[] problems = resourceProfile.getProblems(); for (int i = 0; i < problems.length; i++) { IProblem p = problems[i]; if (p.getId().equals(id)) { list.add(p); } else if (p.getId().startsWith(id + CheckersRegistry.CLONE_SUFFIX)) { list.add(p); } } return list; } /** * Reports a simple problem for given file and line, error message comes * from problem definition * * @param id * - problem id * @param file * - file * @param lineNumber * - line */ public void reportProblem(String id, IFile file, int lineNumber) { reportProblem(id, createProblemLocation(file, lineNumber), EMPTY_OBJECT_ARRAY); } /** * @return problem reporter for given checker * @since 2.0 */ @Override public IProblemReporter getProblemReporter() { return problemReporter; } /** * Convenience method to return codan runtime * * @return */ protected CodanRuntime getRuntime() { return CodanRuntime.getInstance(); } /** * Convenience method to create and return instance of IProblemLocation * * @param file * - file where problem is found * @param line * - line number 1-relative * @return instance of IProblemLocation */ protected IProblemLocation createProblemLocation(IFile file, int line) { return getRuntime().getProblemLocationFactory().createProblemLocation(file, line); } /** * Convenience method to create and return instance of IProblemLocation * * @param file * - file where problem is found * @param startChar * - start char of the problem in the file, is zero-relative * @param endChar * - end char of the problem in the file, is zero-relative and * exclusive. * @return instance of IProblemLocation */ protected IProblemLocation createProblemLocation(IFile file, int startChar, int endChar) { return getRuntime().getProblemLocationFactory().createProblemLocation(file, startChar, endChar, -1); } /** * Defines if checker should be run as user type in editor. Override this * method is checker is too heavy for that (runs too long) */ @Override public boolean runInEditor() { return this instanceof IRunnableInEditorChecker; } /** * report a problem * * @param problemId - id of a problem * @param loc - problem location * @param args - extra problem arguments */ public void reportProblem(String problemId, IProblemLocation loc, Object... args) { getProblemReporter().reportProblem(problemId, loc, args); } /** * Returns the invocation context. * * @return checker invocation context * * @since 2.0 */ protected ICheckerInvocationContext getContext() { return context; } /** * @since 2.0 */ protected void setContext(ICheckerInvocationContext context) { this.context = context; } /** * @since 2.0 */ @Override public void before(IResource resource) { // TODO(sprigogin): Use a problem reporter creating non-persistent editor annotations when running in editor. IProblemReporter reporter = CodanRuntime.getInstance().getProblemReporter(); problemReporter = reporter; if (reporter instanceof IProblemReporterSessionPersistent) { // Create session problem reporter problemReporter = ((IProblemReporterSessionPersistent) reporter).createReporter(resource, this); ((IProblemReporterSessionPersistent) problemReporter).start(); } else if (reporter instanceof IProblemReporterPersistent) { // Delete markers. ((IProblemReporterPersistent) reporter).deleteProblems(resource, this); } } /** * @since 2.0 */ @Override public void after(IResource resource) { if (problemReporter instanceof IProblemReporterSessionPersistent) { // Delete general markers. ((IProblemReporterSessionPersistent) problemReporter).done(); } problemReporter = null; } /** * @param resource the resource to process. * @return true if framework should traverse children of the resource and * run this checkers on them again. * @throws OperationCanceledException if the checker was interrupted. * @since 2.0 */ public abstract boolean processResource(IResource resource) throws OperationCanceledException; /** * @see IChecker#processResource(IResource, ICheckerInvocationContext) * @since 2.0 */ @Override public synchronized boolean processResource(IResource resource, ICheckerInvocationContext context) throws OperationCanceledException { this.setContext(context); try { return processResource(resource); } finally { this.setContext(null); } } }